AshplotR

Introduction

This script can be used to create bi-plots and Harker plots of all tephra major elemental data. It includes interactive exploration of the data and some discussion on identifying useful elements for discrimination. Guidance for saving plots as .svg or .pdf files is also provided. All the code used to produce this document is downloadable as an RMarkdown file. To run this you will require r and RStudio. We are happy for you to use, share and improve our code, but would ask that you cite this as a poin tof origin for the plots.

Load packages

We first load in packages required to generate the plots and manipulate the data. You may need to install these packages in r or update them to work correctly.

library(ggplot2)
library(factoextra)
library(readr)
library(compositions)
library(gganimate)
library(cowplot)
library(tidyverse)
library(gt)
library(plotly)
library(svglite)
library(png)
library(here)
library(ggdensity)

Load your data

Any data placed within the the data file of the r project can be read using the code outlined below. As this is a Markdown script the ‘here’ package is used to ensure that project links do not break when moving scripts around. As long as you start a new R project and drop this script into it (using the structure outlined on the home page) then it will work. Data files should be in .csv format and contain the group of the tephra as column 1 under the title “id” (see example files for reference). Loaded here are some data for core ODP-980 in the North Atlantic and a terrestrial site from the UK called MT.

chem <- here::here("Data","Borrobol_type.csv") %>% read.csv()

Check your data has loaded correctly

The following script produces a summary table of mean values and number of analyses in your data.

chem_sum <- chem %>% group_by(id) %>% dplyr::summarise(                                            
                                                       count=n(),
                                                       SiO2.= mean(SiO2),
                                                       dev_1 = sd(SiO2),
                                                       TiO2. = mean(TiO2),
                                                       dev_2 = sd(TiO2),
                                                       Al2O3. = mean(Al2O3),
                                                       dev_3 = sd(Al2O3),
                                                       FeOt = mean(FeO),
                                                       dev_4 = sd(FeO),
                                                       MnO.= mean(MnO),
                                                       dev_5 = sd(MnO),
                                                       MgO.= mean(MgO),
                                                       dev_6 = sd(MgO),
                                                       CaO.= mean(CaO),
                                                       dev_7 = sd(CaO),
                                                       Na2O. = mean(Na2O),
                                                       dev_8 = sd(Na2O),
                                                       K2O. = mean(K2O),
                                                       dev_9 = sd(K2O),
                                                       P2O5. = mean(P2O5),
                                                       dev_10 = sd(P2O5),
                                                       Total.=mean(Total),
                                                       dev_11 = sd(Total))
chem_sum <- chem_sum %>% mutate(across(where(is.numeric), ~ round(., digits = 2)))
chem_sum %>% rename(layer = id, n = count , SiO2 = SiO2., sd1 = dev_1, TiO2 = TiO2. , sd2 = dev_2)
## # A tibble: 12 x 24
##    layer          n  SiO2   sd1  TiO2   sd2 Al2O3. dev_3  FeOt dev_4  MnO. dev_5
##    <chr>      <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1 Borrobol-~     2  76.4  0.39  0.07  0.01   13.0  0.42  0.95  0.01  0.05  0.01
##  2 Borrobol-~    12  76.4  0.41  0.12  0.01   12.7  0.34  1.56  0.12  0.04  0.01
##  3 Borrobol-~     8  76.4  0.59  0.12  0.01   12.6  0.57  1.47  0.15  0.04  0.01
##  4 Borrobol-~    35  75.9  0.31  0.15  0.01   12.9  0.2   1.58  0.13  0.04  0.01
##  5 Borrobol ~   124  76.4  0.36  0.13  0.01   12.7  0.21  1.55  0.11  0.04  0.01
##  6 Borrobol ~    13  76.5  0.25  0.13  0.01   12.8  0.23  1.53  0.1   0.04  0.01
##  7 Borrobol ~    21  76.5  0.54  0.12  0.02   12.9  0.48  1.36  0.16  0.04  0.01
##  8 CRUM1 597~    28  76.7  0.27  0.13  0.01   12.6  0.21  1.53  0.11  0.04  0.01
##  9 Fosen Tep~    10  76.9  0.49  0.12  0.01   12.3  0.43  1.54  0.2   0.05  0   
## 10 Hasseldal~   104  77.8  0.5   0.09  0.02   12.2  0.32  1.14  0.14  0.04  0.02
## 11 Hovsdalur~    23  77.9  0.53  0.12  0.02   12.3  0.12  1.16  0.12  0.04  0.02
## 12 Penifiler~   171  76.8  0.49  0.12  0.02   12.8  0.31  1.36  0.2   0.04  0.02
## # ... with 12 more variables: MgO. <dbl>, dev_6 <dbl>, CaO. <dbl>, dev_7 <dbl>,
## #   Na2O. <dbl>, dev_8 <dbl>, K2O. <dbl>, dev_9 <dbl>, P2O5. <dbl>,
## #   dev_10 <dbl>, Total. <dbl>, dev_11 <dbl>
gt(chem_sum)
id count SiO2. dev_1 TiO2. dev_2 Al2O3. dev_3 FeOt dev_4 MnO. dev_5 MgO. dev_6 CaO. dev_7 Na2O. dev_8 K2O. dev_9 P2O5. dev_10 Total. dev_11
Borrobol-type Tephra GI-1a 2 76.37 0.39 0.07 0.01 13.04 0.42 0.95 0.01 0.05 0.01 0.04 0.00 0.69 0.18 4.01 0.03 4.77 0.21 0.01 0.01 100 0
Borrobol-type Tephra GI-1e_pt1 12 76.38 0.41 0.12 0.01 12.72 0.34 1.56 0.12 0.04 0.01 0.08 0.03 0.81 0.07 4.13 0.15 3.92 0.11 0.01 0.01 100 0
Borrobol-type Tephra GI-1e_pt2 8 76.42 0.59 0.12 0.01 12.64 0.57 1.47 0.15 0.04 0.01 0.07 0.02 0.84 0.04 4.16 0.20 3.99 0.07 0.01 0.00 100 0
Borrobol-type:GS-2.1-RHY Tephra 35 75.87 0.31 0.15 0.01 12.91 0.20 1.58 0.13 0.04 0.01 0.11 0.02 0.96 0.05 4.27 0.15 3.94 0.10 0.02 0.01 100 0
Borrobol Tephra 124 76.43 0.36 0.13 0.01 12.74 0.21 1.55 0.11 0.04 0.01 0.08 0.02 0.78 0.05 4.26 0.21 3.94 0.10 0.01 0.01 100 0
Borrobol Tephra-Sweden 13 76.50 0.25 0.13 0.01 12.76 0.23 1.53 0.10 0.04 0.01 0.07 0.02 0.77 0.05 4.24 0.32 3.96 0.13 0.01 0.00 100 0
Borrobol Tephra - ASHIK 21 76.46 0.54 0.12 0.02 12.92 0.48 1.36 0.16 0.04 0.01 0.06 0.03 0.70 0.10 4.21 0.51 3.95 0.10 0.01 0.01 100 0
CRUM1 597 Tephra 28 76.67 0.27 0.13 0.01 12.59 0.21 1.53 0.11 0.04 0.01 0.07 0.02 0.77 0.06 4.30 0.14 3.91 0.09 0.00 0.00 100 0
Fosen Tephra 10 76.88 0.49 0.12 0.01 12.31 0.43 1.54 0.20 0.05 0.00 0.07 0.03 0.70 0.12 4.30 0.14 4.02 0.30 0.01 0.00 100 0
Hasseldalen Tephra 104 77.75 0.50 0.09 0.02 12.15 0.32 1.14 0.14 0.04 0.02 0.03 0.02 0.51 0.09 4.03 0.27 4.22 0.24 0.01 0.02 100 0
Hovsdalur Tephra 23 77.88 0.53 0.12 0.02 12.27 0.12 1.16 0.12 0.04 0.02 0.05 0.02 0.49 0.06 3.61 0.24 4.38 0.60 0.01 0.00 100 0
Penifiler Tephra 171 76.78 0.49 0.12 0.02 12.77 0.31 1.36 0.20 0.04 0.02 0.05 0.03 0.69 0.10 4.10 0.40 4.02 0.12 0.01 0.02 100 0

Make TAS calculations

To calculate for the TAS plot the data require normalisation of the data. The rest of the script uses unnormalised data for plotting, but the code below can be used to normalise other data also by replacing the element to be normalise.

TAS_x <- (100/ chem [["Total"]]) * chem [["SiO2"]]
TAS_y <- (100/ chem [["Total"]]) * (chem [["K2O"]] + chem [["Na2O"]])

chem <- cbind(chem, TAS_x, TAS_y)

Filtering mixed datasets

It is possible your datasheet contains multiple types of tephra which would benefit from filtering before plotting. I suggest this is carried out by using silica values as a divisor. Rhyolites >69% silica is a case for this. However, it might be worth plotting everything first before then selecting a filter to ensure vital data is not being excluded.

chem <- filter(chem, SiO2 >68)

Plotting the data

First we generate a series of plots from all possible pairs of elements.

p1 <- ggplot(chem, aes(x = TAS_x, y = TAS_y, fill = id, shape = id))
p2 <- ggplot(chem, aes(x = SiO2, y = TiO2, fill = id, shape = id))
p3 <- ggplot(chem, aes(x = SiO2, y = Al2O3, fill = id, shape = id))
p4 <- ggplot(chem, aes(x = SiO2, y = FeO,  fill = id, shape = id))
p5 <- ggplot(chem, aes(x = SiO2, y = MnO,  fill = id, shape = id))
p6 <- ggplot(chem, aes(x = SiO2, y = MgO,  fill = id, shape = id))
p7 <- ggplot(chem, aes(x = SiO2, y = CaO,  fill = id, shape = id))
p8 <- ggplot(chem, aes(x = SiO2, y = Na2O,  fill = id, shape = id))
p9 <- ggplot(chem, aes(x = SiO2, y = K2O,  fill = id, shape = id))
p47 <- ggplot(chem, aes(x = SiO2, y = K2O, fill = id, shape = id))
p10 <- ggplot(chem, aes(x = SiO2, y = P2O5,  fill = id, shape = id))
p11 <- ggplot(chem, aes(x = TiO2, y = Al2O3,  fill = id, shape = id))
p12 <- ggplot(chem, aes(x = TiO2, y = FeO,  fill = id, shape = id))
p13 <- ggplot(chem, aes(x = TiO2, y = MnO,  fill = id, shape = id))
p14 <- ggplot(chem, aes(x = TiO2, y = MgO,  fill = id, shape = id))
p15 <- ggplot(chem, aes(x = TiO2, y = CaO,  fill = id, shape = id))
p16 <- ggplot(chem, aes(x = TiO2, y = Na2O,  fill = id, shape = id))
p17 <- ggplot(chem, aes(x = TiO2, y = K2O,  fill = id, shape = id))
p18 <- ggplot(chem, aes(x = TiO2, y = P2O5,  fill = id, shape = id))
p19 <- ggplot(chem, aes(x = Al2O3, y = FeO,  fill = id, shape = id))
p20 <- ggplot(chem, aes(x = Al2O3, y = MnO,  fill = id, shape = id))
p21 <- ggplot(chem, aes(x = Al2O3, y = MgO,  fill = id, shape = id))
p22 <- ggplot(chem, aes(x = Al2O3, y = CaO,  fill = id, shape = id))
p23 <- ggplot(chem, aes(x = Al2O3, y = Na2O,  fill = id, shape = id))
p24 <- ggplot(chem, aes(x = Al2O3, y = K2O,  fill = id, shape = id))
p25 <- ggplot(chem, aes(x = Al2O3, y = P2O5,  fill = id, shape = id))
p26 <- ggplot(chem, aes(x = FeO, y = MnO,  fill = id, shape = id))
p27 <- ggplot(chem, aes(x = FeO, y = MgO,  fill = id, shape = id))
p28 <- ggplot(chem, aes(x = FeO, y = CaO,  fill = id, shape = id))
p29 <- ggplot(chem, aes(x = FeO, y = Na2O,  fill = id, shape = id))
p30 <- ggplot(chem, aes(x = FeO, y = K2O,  fill = id, shape = id))
p31 <- ggplot(chem, aes(x = FeO, y = P2O5,  fill = id, shape = id))
p32 <- ggplot(chem, aes(x = MnO, y = MgO,  fill = id, shape = id))
p33 <- ggplot(chem, aes(x = MnO, y = CaO,  fill = id, shape = id))
p34 <- ggplot(chem, aes(x = MnO, y = Na2O,  fill = id, shape = id))
p35 <- ggplot(chem, aes(x = MnO, y = K2O,  fill = id, shape = id))
p36 <- ggplot(chem, aes(x = MnO, y = P2O5,  fill = id, shape = id))
p37 <- ggplot(chem, aes(x = MgO, y = CaO,  fill = id, shape = id))
p38 <- ggplot(chem, aes(x = MgO, y = Na2O,  fill = id, shape = id))
p39 <- ggplot(chem, aes(x = MgO, y = K2O,  fill = id, shape = id))
p40 <- ggplot(chem, aes(x = MgO, y = P2O5,  fill = id, shape = id))
p41 <- ggplot(chem, aes(x = CaO, y = Na2O,  fill = id, shape = id))
p42 <- ggplot(chem, aes(x = CaO, y = K2O,  fill = id, shape = id))
p43 <- ggplot(chem, aes(x = CaO, y = P2O5,  fill = id, shape = id))
p44 <- ggplot(chem, aes(x = Na2O, y = K2O,  fill = id, shape = id))
p45 <- ggplot(chem, aes(x = Na2O, y = P2O5,  fill = id, shape = id))
p46 <- ggplot(chem, aes(x = K2O, y = P2O5,  fill = id, shape = id))

Custom tephra theme

To ensure consistency and to provide a shortcut of coding it everytime we set up[ a custom tephra plotting theme. This means all of our plots will have the same sized fonts etc…

Tephra.theme <-theme_bw()+theme(axis.title.x=element_text(size=16),
                                axis.title.y=element_text(size=16), 
                                axis.text.x=element_text(size=16),
                                axis.text.y=element_text(size=16))+
  theme(panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank())

Custom colour palette

The hex numbers below specify a custom colour palette for plotting. These can be altered but were slected in order to help those with colour vision deficiencies, and this should be considered when making changes. At present 35 layers can be plotted using this pallete. If you have more than 35 groups of data you will either have to specify additional colours or consider splitting your dataset. The latter might be more appropriate for improving the final clarity in the plots.

chempalette <- c("#209A24","#A769EE","#B4C428","#e30303","#000000","#EF139D","#3A700F","#5288FF","#E64701","#7F9AF5","#F36D20","#0B3075","#C18522","#9634A6","#1D7D46","#80ddb8","#7CBC92","#B10E89","#384B27","#F896FD","#C6A766","#20628E","#9C0323","#C3AFE0","#572D24","#FF79A2","#3E6D6F","#E18C63","#6F2B40","#DF9FB4", "#291700", "#7e005b", "#00597a" , "#7b003a",  "#470600")

The palette is known as “chempalette”.

Figures

We first generate the simple bi-plots of each element. This initial explorative approach facilitates data checking for unusual analyses and permits the identification of elements with significant variability.

TAS plot Le Maitre et al. (2002)

SiO2 VS TiO2

SiO2 VS Al2O3

SiO2 VS FeO

SiO2 VS MnO

SiO2 VS MgO

SiO2 VS CaO

SiO2 VS Na2O

SiO2 VS K2O

SiO2 VS P2O5

TiO2 VS Al2O3

TiO2 vs FeO

TiO2 vs MnO

TiO2 VS MgO

TiO2 VS CaO

TiO2 VS Na2O

TiO2 VS K2O

TiO2 VS P2O5

Al2O3 VS FeO

Al2O3 VS MnO

Al2O3 VS MgO

p21 <- p21 + geom_point(aes(fill = id), size=4, alpha=0.8)+xlab("Al2O3 (wt%)")+ylab("MgO (wt%)")+scale_shape_manual(values=c(21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25))+
  scale_fill_manual(values = chempalette) +
  Tephra.theme
p21

Al2O3 VS CaO

Al2O3 VS Na2O

Al2O3 VS K2O

Al2O3 VS P2O5

FeO VS MnO

FeO vs MgO

FeO vs CaO

FeO VS Na2O

FeO VS K2O

FeO VS P2O5

MnO VS MgO

MnO VS CaO

MnO VS Na2O

MnO VS K2O

MnO VS P2O5

MgO VS CaO

MgO VS Na2O

MgO VS K2O

MgO VS P2O5

CaO VS Na2O

CaO VS K2O

CaO VS P2O5

Na2O VS K2O

Na2O VS P2O5

K2O VS P2O5

# {-}

Saving individual plots

We propose exporting your plots in .svg format. This is a vector file format that preserves your data without size and scaling issues. It is also readable and editable by software like Adobe Illustrator, Affinity Designer, or free alternatives like Inkscape. .Using the file structure presented here the all plots can be named appropriately and will be saved in the Output -> Plots folder. The width and height and dpi outputs can be altered but override the preview functions in Rstudio and we recommend that you view the svg file directly in you preferred image editor to understand how it might look.

ggsave( filename = file.path("Script", "Output","Plots","fig1.svg"), plot = p1, width = 12, height = 6, dpi = 300)

Multivariate analysis

Multivariate analysis via ordination is often a helpful way of exploring your data. It permits the identification of useful elements for discrimination and facilitates dimension reduction. Unfortunately, percentage data can have problematic covariation and should be ‘freed’ from their compositional sum where possible. This can be achieved via undertaking a centred log-ratio transform.

centred log-ratio data table

chem_multi <- chem[ -c(1,6,11,12)] ## check columns to drop. Currently dropping id, MnO, P2O5, and Total to perform the clr transform.
chem_multi[is.na(chem_multi)] <- 0.005 # replace NAs with half the detection limit
chem_multi_clr <- clr(chem_multi)
cmclr <- as.data.frame(chem_multi_clr)
head(cmclr)
##      Sites   Country       age     SiO2    Al2O3        FeO       MnO       MgO
## 1 1.642765 0.3618315 0.3618315 3.093085 1.280336 -0.8536068 -4.394162 -3.397470
## 2 1.667643 0.3867093 0.3867093 3.117234 1.315663 -0.7952411 -4.167768 -3.906574
## 3 1.670452 0.3895177 0.3895177 3.118529 1.321894 -0.7552432 -4.170679 -3.650339
## 4 1.652841 0.3719074 0.3719074 3.100923 1.300696 -0.8593681 -4.363371 -3.507648
## 5 1.668021 0.3870871 0.3870871 3.116741 1.313589 -0.7739540 -4.443730 -3.871661
## 6 1.662949 0.3820153 0.3820153 3.110569 1.319112 -0.8551696 -4.348718 -3.800505
##         K2O      P2O5 Cl F    Total    TAS_x     TAS_y
## 1 0.1503695 -5.545292  0 0 3.357564 3.093085 0.8496628
## 2 0.1328745 -5.505815  0 0 3.382442 3.117234 0.8688885
## 3 0.1163958 -5.795532  0 0 3.385250 3.118529 0.8617065
## 4 0.1676347 -5.580336  0 0 3.367640 3.100923 0.8762521
## 5 0.1645933 -5.314697  0 0 3.382819 3.116741 0.8673628
## 6 0.1412168 -5.362589  0 0 3.377748 3.110569 0.8807886

We can summarise the importance of the resulting principal components by summarizing how much of the total variance is captured by each principal component.

PCA summary

Information PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10 PC11 PC12 PC13 PC14 PC15
Standard deviation 2.774224 2.161704 1.413388 0.7742391 0.6098498 0.5320467 0.2919113 0.2413936 0.1237158 0.04010732 0.0306669 0.02399163 0.001124607 8.722397e-16 7.458682e-17
Proportion of Variance 0.487620 0.296070 0.126570 0.0379800 0.0235600 0.0179400 0.0054000 0.0036900 0.0009700 0.00010000 0.0000600 0.00004000 0.000000000 0.000000e+00 0.000000e+00
Cumulative Proportion 0.487620 0.783690 0.910260 0.9482400 0.9718100 0.9897400 0.9951400 0.9988300 0.9998000 0.99990000 0.9999600 1.00000000 1.000000000 1.000000e+00 1.000000e+00

If this has captured a significant amount of variation it would be worth plotting the output in order to identify the important variables in determining the changes observed.

PCA scores scree plot

This is a visual representation of the summary table showing the percentage of the total variance explained by each dimension.

Variables PCA plot

Loadings dimension 1

Loadings dimension 2

PCA - Biplot

PCA - grouped

## Scale for 'shape' is already present. Adding another scale for 'shape', which
## will replace the existing scale.

Interactive figures

The function ggplotly within the plotly package is extremely useful for interactively examining data. ggplotly plots allow you to zoom into areas of interest and turn layers on and off as well as saving low resolution .png files of zoomed sections of your plots.We refer to these as iPlots in order to distinguish them from static plots presented above.

iTAS plot

iFeO-CaO

iK-lines

iTiO2 vs Al2O3

iK2O vs CaO

Saving all figures to a .pdf

l <- list(p1, p2, p3, p4, p5, p6, p7, p8, p9, p47, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46)
pdf("allplotsout.pdf", width = 12, height = 6)
invisible(lapply(l, print))
dev.off()
## png 
##   2

Harker plot

It is frequently useful to plot all of the collected elemental data against SiO[2]. This permits an assessme tof groupings within the data and which elements might be useful discriminators. Additionally, wt% K2O vs SiO2 can further classify the tephra to low, mid and high Potassium values. The dividing lines included here are from xxxxxxxx.

g1 <- plot_grid(p1 + theme(legend.position = "none"), 
                p2 + theme(legend.position = "none"),
                p3 + theme(legend.position="none"),
                p4 + theme(legend.position="none"),
                p5 + theme(legend.position="none"),
                p6 + theme(legend.position="none"),
                p7 + theme(legend.position="none"),
                p8 + theme(legend.position="none"), 
                p47 + theme(legend.position="none"), 
                p10 + theme(legend.position="none"),
                labels = c("A", "B", "C", "D", "E", "F", "G", "H", "I", "J"), align = "b")
legend <- get_legend(p1)
legplot <- plot_grid(legend)
px <- plot_grid( g1, rel_widths = c(4, 1))
l2 <- list(px,legplot)
pdf("Script/Output/Plots/Harkerplot.pdf", width = 30, height = 20)
invisible(lapply(l2, print))
dev.off()
## png 
##   2
ggsave( filename = file.path("Script","Output","Plots","Harker.svg"), plot = px, width = 30, height = 20, dpi = 300)

print(g1)

Other useful R tricks

Creating an inset within a figure

p100 <- ggplot(chem, aes(x = TAS_x, y = TAS_y, fill = id, shape = id))
p100 <- p100 + geom_point(aes(fill = id), size=4, alpha=0.8)+xlab("SiO2 (wt%)")+ylab("Na2O+K2O (wt%)")+
  scale_shape_manual(values=c(21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25))+
  scale_fill_manual(values = chempalette) +geom_segment(x=77,y=0,xend=69,yend=8)+ 
  geom_segment(x=69, y=8,xend=69,yend=13)+geom_segment(x=41, y=7,xend=52.5,yend=14)+
  geom_segment(x=52.5,y=14,xend=57.6,yend=11.7)+geom_segment(x=45,y=0,xend=45,yend=5)+
  geom_segment(x=45,y=5,xend=63,yend=14.56)+geom_segment(x=52,y=0,xend=52,yend=5)+
  geom_segment(x=52,y=5,xend=63,yend=7)+geom_segment(x=57,y=0,xend=57,yend=5.9)+
  geom_segment(x=63,y=0,xend=63,yend=7)+geom_segment(x=45,y=5,xend=52,yend=5)+
  geom_segment(x=52,y=5,xend=49.4,yend=7.3)+geom_segment(x=57,y=5.9,xend=53,yend=9.3)+
  geom_segment(x=63,y=7,xend=57.6,yend=11.7)+geom_segment(x=49.4,y=7.3,xend=45,yend=9.4)+
  geom_segment(x=53,y=9.3,xend=48.4,yend=11.5)+geom_segment(x=41,y=0,xend=41,yend=7)+
  geom_segment(x=52.5,y=14,xend=49,yend=15.5)+geom_segment(x=41,y=3,xend=45,yend=3)+
  geom_segment(x=63,y=7,xend=69,yend=8)+
  scale_x_continuous(limits=c(74, 79), expand = c(0, 0)) + ## set x axis of insert
  scale_y_continuous(limits=c(6, 10.5), expand = c(0, 0)) + ## set y axis of insert
  theme_bw()+theme(axis.title.x=element_text(size=9), axis.title.y=element_text(size=9), 
                   axis.text.x=element_text(size=9), axis.text.y=element_text(size=9))+ ## change the text size as neccessary
  theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position = "none")
fig_in <- p1 + annotation_custom(ggplotGrob(p100), xmin = 40, xmax = 56, ymin = 7, ymax = 16) + ## place the insert
   annotate("rect", xmin = 74, xmax = 79, ymin = 6, ymax = 10.5,
  alpha = .2) ## use this to highlight the area of the insert plot
ggsave( filename = file.path("Script", "Output","Plots","insert_plot.svg"), plot = fig_in, width = 10, height = 6, dpi = 300)

print(fig_in)

## Creating a HDR plot to simplify your data. Simplifying the data we create to make more visually compelling figures can be acheived using highest density regions. The following code permits this as an addition to the previosuly created plots. It can be added easily to any of the previously created plots by changing the p code. Visibility of the density regions can be applied to just reference data or entire datasets. Opacity is varied using the alpha command and the probability range can be altered in the ‘probs’ argument. You may need to vary the x and y axes in order to fit the full range in to the plot.

p28den <- p28 +
geom_hdr(stat= "hdr", method = "kde", na.rm = TRUE, inherit.aes = TRUE, alpha  = 0.3, xlim = c(0,100), ylim = c(0,30), smooth = TRUE, n = 1000, probs = c(0.75))
print(p28den)

The plots are nice but messy and still have lots of overplotting. If you have particularly messy data I’d suggest creating plot ‘facets’ using the following code.

p28den_facet <- p28 +
geom_hdr(method = "kde", alpha  = 0.5, xlim = c(0,100), ylim = c(0,30), show.legend = FALSE, smooth = TRUE, n = 1000, probs = c(0.95)) +
  facet_wrap(~ id)


print(p28den_facet)

chem2 <- dplyr::select(chem, -Total)
chem2 <- rename(chem2, id2=id)
f19 <- ggplot(chem, aes(x = Al2O3, y = CaO,  fill = id, shape = id))

f19 <- f19 + 
    geom_point(data = chem2, inherit.aes = FALSE, aes(x=Al2O3, y = CaO, shape = id2), colour = "grey70") +
  geom_point(aes(fill = id), size=4, alpha=0.8)+xlab("Al2O3 (wt%)")+ylab("CaO (wt%)")+scale_shape_manual(values=c(21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25))+
  scale_fill_manual(values = chempalette) +
  Tephra.theme +
  facet_wrap(~ id)

ggsave( filename = file.path("Script", "Output","Plots","faceted plot.pdf"), plot = f19, width = 25, height = 16, units = "cm", dpi = 300)

print(f19)

unknowns <- here::here("Data","Ardtoe_16.5_B_type.csv") %>% read.csv()
gt(unknowns)
id2 SiO2 TiO2 Al2O3 FeO MnO MgO CaO Na2O K2O Cl P2O5 Total
380 76.00313 0.13204995 12.90136 1.5669031 0.05215766 0.073890020 0.8094786 4.229427 4.206867 0 0.024940469 100
387 76.59048 0.12320307 12.46894 1.5890809 0.05106648 0.039752971 0.7755462 4.462193 3.900151 0 0.005189683 100
387 75.92839 0.11049529 13.42150 1.3561821 0.05105359 0.052917614 0.6484738 4.296372 4.118461 0 0.016258445 100
410 77.24444 0.11317187 11.92802 1.3273489 0.04997470 0.024466780 0.6460271 4.554777 4.095010 0 0.016658233 100
410 76.65740 0.14601109 12.19382 1.4629552 0.03929447 0.111457235 0.8955557 4.487471 3.965581 0 0.040453288 100
420 76.25817 0.14687726 12.63333 1.5402689 0.03212612 0.093858662 0.8514471 4.611148 3.811250 0 0.021627387 100
420 77.32078 0.10893876 12.62702 1.1756351 0.02867915 0.024266975 0.5681203 4.075696 4.062144 0 0.008824354 100
420 76.94974 0.11294698 12.32582 1.3819579 0.05475269 0.055065562 0.6674614 4.356958 4.079858 0 0.015330753 100
420 77.23369 0.10020921 11.99594 1.4343671 0.03381673 0.025853769 0.6393120 4.414686 4.112197 0 0.010031262 100
420 76.05568 0.10702770 12.62792 1.5104649 0.04185324 0.086829867 0.7079653 4.610416 4.240192 0 0.011764718 100
420 75.52786 0.16410136 13.05794 1.6359643 0.03976302 0.097514075 0.9487373 4.601044 3.897197 0 0.029980055 100
420 76.54834 0.12191103 12.38466 1.3845089 0.04515610 0.076546362 0.6711885 4.759640 3.979889 0 0.028157381 100
420 76.39237 0.15275863 12.77143 1.5077351 0.06188900 0.097238986 0.8168712 4.433079 3.745612 0 0.021018907 100
442 77.21185 0.10646580 12.22102 1.2313233 0.03903392 0.071260827 0.7180326 4.497622 3.883715 0 0.019782857 100
442 76.69401 0.10237887 12.23788 1.3744285 0.03858815 0.053542372 0.7210442 4.747284 4.009403 0 0.021542439 100
442 76.47075 0.11102017 12.70541 1.1456694 0.04764003 0.067577494 0.6471280 4.583412 4.204076 0 0.017314109 100
442 76.74392 0.11867632 12.73449 1.1364819 0.03539469 0.014157877 0.5949431 4.177302 4.424961 0 0.019779387 100
454 75.76463 0.13949886 12.82045 1.5436909 0.05801250 0.074144316 0.7587125 4.976045 3.837304 0 0.027506817 100
454 75.46961 0.12623091 13.23725 1.6791525 0.04617695 0.102673364 0.8101293 4.674400 3.828935 0 0.025538045 100
454 75.56446 0.14010431 12.78176 1.7300202 0.05034506 0.095329786 0.8687938 4.773006 3.975683 0 0.020390274 100
454 76.31437 0.13383242 12.64378 1.5893251 0.05717821 0.089464629 0.8199709 4.441466 3.884265 0 0.026245735 100
454 75.97227 0.14575976 12.91750 1.5434188 0.03583741 0.091270132 0.8381972 4.493089 3.951337 0 0.011526653 100
454 75.98706 0.14838109 13.24833 1.4673473 0.03240626 0.109201816 0.8817421 4.331603 3.768921 0 0.025008049 100
454 76.04285 0.15673637 12.86868 1.6107275 0.04817031 0.079308605 0.7418855 4.458836 3.981417 0 0.011494001 100
475 77.17689 0.11083083 12.21404 1.3087988 0.02836931 0.064783636 0.7981513 4.204691 4.080099 0 0.013443663 100
475 76.62986 0.11424276 12.72582 1.2411494 0.03463182 0.020905791 0.6802829 4.507521 4.027532 0 0.018160586 100
475 76.14597 0.16576605 12.68678 1.4035489 0.04758683 0.112716714 0.9232686 4.548167 3.944770 0 0.021324784 100
480 75.72011 0.13144165 13.14479 1.4961183 0.04974306 0.113033613 0.8535951 4.578947 3.895368 0 0.016960213 100
480 75.52408 0.10334690 13.10485 1.4388347 0.02739943 0.048548039 0.6299785 5.011074 4.104393 0 0.007605165 100
480 76.60738 0.11195173 12.47452 1.5198642 0.05286032 0.066568700 0.7041120 4.360925 4.085303 0 0.016616212 100
505-510 76.65605 0.09946791 12.89805 1.1464222 0.02530779 0.025722672 0.5703588 4.287181 4.276187 0 0.015350627 100
505-510 76.71721 0.09672477 12.37239 1.2699973 0.03887854 0.039612095 0.5796151 4.449968 4.429743 0 0.005868459 100
505-510 76.05787 0.14955098 12.52087 1.7823156 0.04245861 0.093955429 0.8774428 4.393625 4.065622 0 0.016289812 100
505-510 76.24703 0.14635568 12.82195 1.6703978 0.04826290 0.117941159 0.8152461 4.284743 3.835020 0 0.013058144 100
505-510 75.73803 0.14102717 12.70740 1.7781055 0.03686645 0.120984282 0.8963222 4.742584 3.830373 0 0.008307934 100
505-510 76.85715 0.11324408 12.43627 1.2549926 0.02068385 0.003516254 0.5168894 4.387768 4.390457 0 0.019029141 100
505-510 77.57019 0.10721989 11.96031 1.0596218 0.02662156 0.026516747 0.5913339 4.564025 4.078863 0 0.015406964 100
505-510 76.75269 0.10856079 13.10689 0.9835177 0.03759059 0.008319228 0.5732051 4.347156 4.061119 0 0.020952131 100
505-510 76.90239 0.12989825 12.50208 1.3284093 0.03730896 0.050445921 0.7178034 3.868151 4.447649 0 0.015869446 100
505-510 77.16865 0.11003945 12.48262 1.3499987 0.04051881 0.045858496 0.7008602 3.895355 4.192597 0 0.013610969 100
505-510 76.27339 0.10607059 12.78489 1.3079264 0.04881953 0.019569451 0.6909682 4.674601 4.078669 0 0.014885274 100
505-510 77.51055 0.09643494 12.04243 1.3480998 0.03696149 0.035600305 0.6335807 4.122411 4.162199 0 0.011727159 100
505-510 76.83687 0.09935218 12.23137 1.3357812 0.04441136 0.074435944 0.6581430 4.373894 4.322289 0 0.023352453 100
505-510 76.88847 0.10963497 12.17229 1.3376924 0.03654499 0.042271412 0.6928972 4.684943 4.021927 0 0.013535181 100
505-510 76.89560 0.09150607 12.56363 1.1051038 0.03174278 0.004756247 0.6305130 4.479868 4.181465 0 0.015716296 100
505-510 77.18127 0.11148237 12.42395 0.9811715 0.02153637 0.023647775 0.5991122 4.429524 4.223134 0 0.004961810 100
520-524 76.46034 0.11591999 12.34764 1.4231522 0.04443073 0.076753566 0.6535108 4.732294 4.123320 0 0.022531225 100
520-524 77.19453 0.11599690 12.73675 1.2753384 0.04936929 0.063071355 0.6914838 3.803527 4.056754 0 0.012969897 100
520-524 77.29433 0.10890360 11.97877 1.4754344 0.02764476 0.029634346 0.5058782 4.020428 4.541804 0 0.017173260 100
520-524 77.35520 0.10626971 11.70494 1.2323338 0.04144830 0.027112799 0.5122345 4.537394 4.475274 0 0.007894915 100
520-524 77.95664 0.11758516 11.93040 1.2341688 0.02620047 0.037821642 0.5859185 4.178024 3.918977 0 0.014367998 100
520-524 76.54875 0.10491271 12.84308 1.3202392 0.04131332 0.030380535 0.6189640 4.446491 4.033673 0 0.012404509 100
520-524 75.54970 0.14337933 12.87527 1.7624238 0.05149390 0.102670599 0.9275247 4.751079 3.822709 0 0.013745806 100
520-524 75.92387 0.14512247 12.74070 1.7208580 0.04616577 0.125352159 0.9112219 4.484389 3.886022 0 0.016299987 100
520-524 75.96993 0.15329138 12.74084 1.6926837 0.03009401 0.106896440 0.9011485 4.511803 3.881396 0 0.011703227 100
520-524 77.27263 0.11252922 12.13558 1.2587257 0.04014444 0.029016316 0.6558311 4.393632 4.091925 0 0.009984109 100
575-579 76.04575 0.15342392 12.63895 1.5826292 0.04766769 0.094716315 0.8835031 4.670918 3.867686 0 0.014754284 100
575-579 75.96736 0.14624645 12.64964 1.7403431 0.04519965 0.097915179 0.8515907 4.646900 3.823598 0 0.031316155 100
605-609 76.23718 0.14228793 13.05039 1.5928460 0.02999413 0.085562195 0.8694087 4.190548 3.789048 0 0.012629106 100
605-609 76.49533 0.13253017 12.85034 1.4540181 0.04650739 0.083903993 0.8073641 4.090743 4.002178 0 0.037078785 100
605-609 76.45414 0.06636754 12.85458 1.0322203 0.05258918 0.075412878 0.8326970 4.011607 4.594296 0 0.026189409 100
605-609 76.51119 0.13518393 12.34711 1.6006652 0.04506131 0.112497177 0.8646985 4.492810 3.870798 0 0.019980997 100
605-609 76.83272 0.13504035 12.65311 1.5101873 0.04592211 0.109353327 0.9304993 3.969117 3.795598 0 0.018452719 100
605-609 76.16139 0.12978653 12.58511 1.5135492 0.04984555 0.100736084 0.8987874 4.658730 3.878862 0 0.023094061 100
605-609 76.23662 0.13762903 12.75444 1.4864571 0.03350599 0.104653197 0.8986179 4.328104 3.993787 0 0.026083776 100
655-659 76.47049 0.12827809 12.42383 1.6668869 0.03693327 0.087807547 0.7680039 4.594291 3.809017 0 0.014565233 100
655-659 75.65204 0.13396388 12.84060 1.7914653 0.03577266 0.092211631 0.8448012 4.766471 3.837011 0 0.005769784 100
655-659 75.27886 0.15208143 13.58467 1.3514673 0.03711573 0.110416699 0.8980145 4.567302 3.987304 0 0.032773496 100
655-659 76.59546 0.12812480 12.34196 1.6668693 0.04998218 0.074401747 0.8927170 4.189670 4.041179 0 0.019639567 100
655-659 75.96815 0.14878880 13.20294 1.4516593 0.04544289 0.073085561 0.8291756 4.398222 3.862226 0 0.020313179 100
655-659 76.17420 0.13646579 13.12513 1.6005517 0.03745506 0.071154179 0.7814440 4.169614 3.877798 0 0.026395905 100
655-659 76.51764 0.13979448 12.83405 1.5541126 0.04818713 0.099897615 0.8837416 4.085129 3.817975 0 0.019585736 100
655-659 76.50526 0.14789827 12.54891 1.5670923 0.03881018 0.119682218 0.8965153 4.335098 3.820600 0 0.019929554 100
655-659 76.06042 0.15925514 12.67322 1.4786484 0.05235356 0.103766635 0.9430955 4.498749 4.009802 0 0.020795126 100
795-799 75.33530 0.13666351 13.58413 1.5086099 0.03983466 0.087942663 0.8680891 4.492328 3.939545 0 0.007354090 100
795-799 75.98120 0.13920379 12.90177 1.5876109 0.02271439 0.080750700 0.8788802 4.534543 3.854465 0 0.018859196 100
795-799 76.02033 0.14636837 12.72681 1.6261987 0.04571390 0.090064775 0.8310284 4.535322 3.953833 0 0.024429677 100
795-799 76.09458 0.15805704 12.89237 1.7420794 0.03933120 0.124583675 0.9393463 4.105508 3.875692 0 0.028452359 100
795-799 76.11842 0.13950288 12.91580 1.5388064 0.05046292 0.107181583 0.8208566 4.333660 3.969263 0 0.006151472 100
795-799 76.56116 0.13616181 12.37317 1.6105731 0.03365097 0.106769143 0.8507257 4.305871 4.007686 0 0.014332823 100
795-799 77.44136 0.13002308 12.22340 1.5432906 0.04673831 0.071960517 0.8779389 3.626028 4.011361 0 0.028001804 100
855-859 76.52489 0.14146244 12.69460 1.5045983 0.04330911 0.102033326 0.8832751 4.261071 3.824834 0 0.020029152 100
855-859 76.32537 0.14330571 13.02532 1.4287049 0.03301339 0.107320056 0.8976245 4.112343 3.908849 0 0.018152057 100
855-859 76.57861 0.14483409 12.49259 1.5230940 0.03135476 0.100916660 0.9157252 4.354056 3.829434 0 0.029278290 100
unknown_sum <- unknowns %>% group_by(id2) %>% dplyr::summarise(                                            
                                                       count=n(),
                                                       SiO2.= mean(SiO2),
                                                       dev_1 = sd(SiO2),
                                                       TiO2. = mean(TiO2),
                                                       dev_2 = sd(TiO2),
                                                       Al2O3. = mean(Al2O3),
                                                       dev_3 = sd(Al2O3),
                                                       FeOt = mean(FeO),
                                                       dev_4 = sd(FeO),
                                                       MnO.= mean(MnO),
                                                       dev_5 = sd(MnO),
                                                       MgO.= mean(MgO),
                                                       dev_6 = sd(MgO),
                                                       CaO.= mean(CaO),
                                                       dev_7 = sd(CaO),
                                                       Na2O. = mean(Na2O),
                                                       dev_8 = sd(Na2O),
                                                       K2O. = mean(K2O),
                                                       dev_9 = sd(K2O),
                                                       P2O5. = mean(P2O5),
                                                       dev_10 = sd(P2O5),
                                                       Total.=mean(Total),
                                                       dev_11 = sd(Total))
unknown_sum <- unknown_sum %>% mutate(across(where(is.numeric), ~ round(., digits = 2)))
unknown_sum %>% rename(layer = id2, n = count , SiO2 = SiO2., sd1 = dev_1, TiO2 = TiO2. , sd2 = dev_2)
## # A tibble: 15 x 24
##    layer       n  SiO2   sd1  TiO2   sd2 Al2O3. dev_3  FeOt dev_4  MnO. dev_5
##    <chr>   <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
##  1 380         1  76   NA     0.13 NA      12.9 NA     1.57 NA     0.05 NA   
##  2 387         2  76.3  0.47  0.12  0.01   13.0  0.67  1.47  0.16  0.05  0   
##  3 410         2  77.0  0.42  0.13  0.02   12.1  0.19  1.4   0.1   0.04  0.01
##  4 420         8  76.5  0.61  0.13  0.02   12.6  0.32  1.45  0.14  0.04  0.01
##  5 442         4  76.8  0.31  0.11  0.01   12.5  0.28  1.22  0.11  0.04  0.01
##  6 454         7  75.9  0.29  0.14  0.01   12.9  0.23  1.59  0.09  0.05  0.01
##  7 475         3  76.6  0.52  0.13  0.03   12.5  0.28  1.32  0.08  0.04  0.01
##  8 480         3  76.0  0.58  0.12  0.01   12.9  0.38  1.48  0.04  0.04  0.01
##  9 505-510    16  76.8  0.5   0.11  0.02   12.5  0.31  1.31  0.25  0.04  0.01
## 10 520-524    10  76.8  0.78  0.12  0.02   12.4  0.44  1.44  0.21  0.04  0.01
## 11 575-579     2  76.0  0.06  0.15  0.01   12.6  0.01  1.66  0.11  0.05  0   
## 12 605-609     7  76.4  0.23  0.13  0.03   12.7  0.23  1.46  0.19  0.04  0.01
## 13 655-659     9  76.1  0.45  0.14  0.01   12.8  0.4   1.57  0.13  0.04  0.01
## 14 795-799     7  76.2  0.65  0.14  0.01   12.8  0.44  1.59  0.08  0.04  0.01
## 15 855-859     3  76.5  0.13  0.14  0      12.7  0.27  1.49  0.05  0.04  0.01
## # ... with 12 more variables: MgO. <dbl>, dev_6 <dbl>, CaO. <dbl>, dev_7 <dbl>,
## #   Na2O. <dbl>, dev_8 <dbl>, K2O. <dbl>, dev_9 <dbl>, P2O5. <dbl>,
## #   dev_10 <dbl>, Total. <dbl>, dev_11 <dbl>
gt(unknown_sum)
id2 count SiO2. dev_1 TiO2. dev_2 Al2O3. dev_3 FeOt dev_4 MnO. dev_5 MgO. dev_6 CaO. dev_7 Na2O. dev_8 K2O. dev_9 P2O5. dev_10 Total. dev_11
380 1 76.00 NA 0.13 NA 12.90 NA 1.57 NA 0.05 NA 0.07 NA 0.81 NA 4.23 NA 4.21 NA 0.02 NA 100 NA
387 2 76.26 0.47 0.12 0.01 12.95 0.67 1.47 0.16 0.05 0.00 0.05 0.01 0.71 0.09 4.38 0.12 4.01 0.15 0.01 0.01 100 0
410 2 76.95 0.42 0.13 0.02 12.06 0.19 1.40 0.10 0.04 0.01 0.07 0.06 0.77 0.18 4.52 0.05 4.03 0.09 0.03 0.02 100 0
420 8 76.54 0.61 0.13 0.02 12.55 0.32 1.45 0.14 0.04 0.01 0.07 0.03 0.73 0.13 4.48 0.21 3.99 0.17 0.02 0.01 100 0
442 4 76.78 0.31 0.11 0.01 12.47 0.28 1.22 0.11 0.04 0.01 0.05 0.03 0.67 0.06 4.50 0.24 4.13 0.24 0.02 0.00 100 0
454 7 75.87 0.29 0.14 0.01 12.93 0.23 1.59 0.09 0.05 0.01 0.09 0.01 0.82 0.05 4.59 0.23 3.89 0.08 0.02 0.01 100 0
475 3 76.65 0.52 0.13 0.03 12.54 0.28 1.32 0.08 0.04 0.01 0.07 0.05 0.80 0.12 4.42 0.19 4.02 0.07 0.02 0.00 100 0
480 3 75.95 0.58 0.12 0.01 12.91 0.38 1.48 0.04 0.04 0.01 0.08 0.03 0.73 0.11 4.65 0.33 4.03 0.12 0.01 0.01 100 0
505-510 16 76.77 0.50 0.11 0.02 12.50 0.31 1.31 0.25 0.04 0.01 0.05 0.04 0.67 0.11 4.37 0.25 4.16 0.19 0.01 0.00 100 0
520-524 10 76.75 0.78 0.12 0.02 12.40 0.44 1.44 0.21 0.04 0.01 0.06 0.04 0.70 0.16 4.39 0.30 4.08 0.25 0.01 0.00 100 0
575-579 2 76.01 0.06 0.15 0.01 12.64 0.01 1.66 0.11 0.05 0.00 0.10 0.00 0.87 0.02 4.66 0.02 3.85 0.03 0.02 0.01 100 0
605-609 7 76.42 0.23 0.13 0.03 12.73 0.23 1.46 0.19 0.04 0.01 0.10 0.01 0.87 0.04 4.25 0.26 3.99 0.28 0.02 0.01 100 0
655-659 9 76.14 0.45 0.14 0.01 12.84 0.40 1.57 0.13 0.04 0.01 0.09 0.02 0.86 0.06 4.40 0.23 3.90 0.09 0.02 0.01 100 0
795-799 7 76.22 0.65 0.14 0.01 12.80 0.44 1.59 0.08 0.04 0.01 0.10 0.02 0.87 0.04 4.28 0.33 3.94 0.06 0.02 0.01 100 0
855-859 3 76.48 0.13 0.14 0.00 12.74 0.27 1.49 0.05 0.04 0.01 0.10 0.00 0.90 0.02 4.24 0.12 3.85 0.05 0.02 0.01 100 0
chem_red <- filter(chem, age == "WI"|age == "GS2")

c28 <- ggplot(chem_red, aes(x = FeO, y = CaO,  fill = id, shape = id))
c28 <- c28 + 
  geom_hdr(method = "kde", alpha  = 0.5, xlim = c(0,100), ylim = c(0,30), show.legend = FALSE, smooth = TRUE, n = 1000, probs = c(0.95)) +
   scale_fill_manual(values = chempalette) +
    geom_point(data = unknowns, inherit.aes = FALSE, aes(x=FeO, y = CaO, shape = id2, fill = id2), size=4, alpha=0.8) +
  xlab("FeO (wt%)") +
  ylab("CaO (wt%)") + 
   scale_fill_manual(values = chempalette) +
  scale_shape_manual(values=c(1:5,7,11, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25)) +
  Tephra.theme
## Scale for 'fill' is already present. Adding another scale for 'fill', which
## will replace the existing scale.
print(c28)

u28 <- ggplot(chem_red, aes(x = FeO, y = CaO,  fill = id, shape = id))
u28 <- u28 + geom_point(aes(fill = id), size=4, alpha=0.8)+xlab("FeO (wt%)")+ylab("CaO (wt%)")+scale_shape_manual(values=c(21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25, 21:25))+
      geom_point(data = unknowns, inherit.aes = FALSE, aes(x=FeO, y = CaO, shape = id2, fill = id2), size=4, alpha=0.8) +
  scale_fill_manual(values = chempalette) +
  Tephra.theme

ggplotly(u28, width = 1000, height = 800)

References

R. W. Le Maitre (editor), A. Streckeisen, B. Zanettin, M. J. Le Bas, B. Bonin, P. Bateman, G. Bellieni, A. Dudek, S. Efremova, J. Keller, J. Lamere, P. A. Sabine, R. Schmid, H. Sorensen, and A. R. Woolley, Igneous Rocks: A Classification and Glossary of Terms, Recommendations of the International Union of Geological Sciences, Subcommission of the Systematics of Igneous Rocks. Cambridge University Press, 2002.

LS0tDQp0aXRsZTogImluZGV4Ig0KYXV0aG9yOiAiSWFuIE1hdHRoZXdzIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDogdHJ1ZQ0KICAgIHRoZW1lOiB1bml0ZWQNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQotLS0NCg0KIyBBc2hwbG90Ug0KDQojIEludHJvZHVjdGlvbg0KDQpUaGlzIHNjcmlwdCBjYW4gYmUgdXNlZCB0byBjcmVhdGUgYmktcGxvdHMgYW5kIEhhcmtlciBwbG90cyBvZiBhbGwgdGVwaHJhIG1ham9yIGVsZW1lbnRhbCBkYXRhLiBJdCBpbmNsdWRlcyBpbnRlcmFjdGl2ZSBleHBsb3JhdGlvbiBvZiB0aGUgZGF0YSBhbmQgc29tZSBkaXNjdXNzaW9uIG9uIGlkZW50aWZ5aW5nIHVzZWZ1bCBlbGVtZW50cyBmb3IgZGlzY3JpbWluYXRpb24uIEd1aWRhbmNlIGZvciBzYXZpbmcgcGxvdHMgYXMgLnN2ZyBvciAucGRmIGZpbGVzIGlzIGFsc28gcHJvdmlkZWQuIEFsbCB0aGUgY29kZSB1c2VkIHRvIHByb2R1Y2UgdGhpcyBkb2N1bWVudCBpcyBkb3dubG9hZGFibGUgYXMgYW4gUk1hcmtkb3duIGZpbGUuIFRvIHJ1biB0aGlzIHlvdSB3aWxsIHJlcXVpcmUgciBhbmQgUlN0dWRpby4gV2UgYXJlIGhhcHB5IGZvciB5b3UgdG8gdXNlLCBzaGFyZSBhbmQgaW1wcm92ZSBvdXIgY29kZSwgYnV0IHdvdWxkIGFzayB0aGF0IHlvdSBjaXRlIHRoaXMgYXMgYSBwb2luIHRvZiBvcmlnaW4gZm9yIHRoZSBwbG90cy4NCg0KIyMgTG9hZCBwYWNrYWdlcw0KDQpXZSBmaXJzdCBsb2FkIGluIHBhY2thZ2VzIHJlcXVpcmVkIHRvIGdlbmVyYXRlIHRoZSBwbG90cyBhbmQgbWFuaXB1bGF0ZSB0aGUgZGF0YS4gWW91IG1heSBuZWVkIHRvIGluc3RhbGwgdGhlc2UgcGFja2FnZXMgaW4gciBvciB1cGRhdGUgdGhlbSB0byB3b3JrIGNvcnJlY3RseS4NCg0KYGBge3IgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nID0gRkFMU0UsIGVjaG89VFJVRX0NCmxpYnJhcnkoZ2dwbG90MikNCmxpYnJhcnkoZmFjdG9leHRyYSkNCmxpYnJhcnkocmVhZHIpDQpsaWJyYXJ5KGNvbXBvc2l0aW9ucykNCmxpYnJhcnkoZ2dhbmltYXRlKQ0KbGlicmFyeShjb3dwbG90KQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGd0KQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KHN2Z2xpdGUpDQpsaWJyYXJ5KHBuZykNCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZ2dkZW5zaXR5KQ0KYGBgDQoNCg0KIyMgTG9hZCB5b3VyIGRhdGENCg0KQW55IGRhdGEgcGxhY2VkIHdpdGhpbiB0aGUgdGhlIGRhdGEgZmlsZSBvZiB0aGUgciBwcm9qZWN0IGNhbiBiZSByZWFkIHVzaW5nIHRoZSBjb2RlIG91dGxpbmVkIGJlbG93LiBBcyB0aGlzIGlzIGEgTWFya2Rvd24gc2NyaXB0IHRoZSAnaGVyZScgcGFja2FnZSBpcyB1c2VkIHRvIGVuc3VyZSB0aGF0IHByb2plY3QgbGlua3MgZG8gbm90IGJyZWFrIHdoZW4gbW92aW5nIHNjcmlwdHMgYXJvdW5kLiBBcyBsb25nIGFzIHlvdSBzdGFydCBhIG5ldyBSIHByb2plY3QgYW5kIGRyb3AgdGhpcyBzY3JpcHQgaW50byBpdCAodXNpbmcgdGhlIHN0cnVjdHVyZSBvdXRsaW5lZCBvbiB0aGUgaG9tZSBwYWdlKSB0aGVuIGl0IHdpbGwgd29yay4gRGF0YSBmaWxlcyBzaG91bGQgYmUgaW4gLmNzdiBmb3JtYXQgYW5kIGNvbnRhaW4gdGhlIGdyb3VwIG9mIHRoZSB0ZXBocmEgYXMgY29sdW1uIDEgdW5kZXIgdGhlIHRpdGxlICJpZCIgKHNlZSBleGFtcGxlIGZpbGVzIGZvciByZWZlcmVuY2UpLiBMb2FkZWQgaGVyZSBhcmUgc29tZSBkYXRhIGZvciBjb3JlIE9EUC05ODAgaW4gdGhlIE5vcnRoIEF0bGFudGljIGFuZCBhIHRlcnJlc3RyaWFsIHNpdGUgZnJvbSB0aGUgVUsgY2FsbGVkIE1ULg0KDQpgYGB7cn0NCmNoZW0gPC0gaGVyZTo6aGVyZSgiRGF0YSIsIkJvcnJvYm9sX3R5cGUuY3N2IikgJT4lIHJlYWQuY3N2KCkNCmBgYA0KDQojIyBDaGVjayB5b3VyIGRhdGEgaGFzIGxvYWRlZCBjb3JyZWN0bHkNCg0KVGhlIGZvbGxvd2luZyBzY3JpcHQgcHJvZHVjZXMgYSBzdW1tYXJ5IHRhYmxlIG9mIG1lYW4gdmFsdWVzIGFuZCBudW1iZXIgb2YgYW5hbHlzZXMgaW4geW91ciBkYXRhLg0KDQpgYGB7cn0NCmNoZW1fc3VtIDwtIGNoZW0gJT4lIGdyb3VwX2J5KGlkKSAlPiUgZHBseXI6OnN1bW1hcmlzZSggICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdW50PW4oKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTaU8yLj0gbWVhbihTaU8yKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfMSA9IHNkKFNpTzIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRpTzIuID0gbWVhbihUaU8yKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfMiA9IHNkKFRpTzIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFsMk8zLiA9IG1lYW4oQWwyTzMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldl8zID0gc2QoQWwyTzMpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZlT3QgPSBtZWFuKEZlTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzQgPSBzZChGZU8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1uTy49IG1lYW4oTW5PKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfNSA9IHNkKE1uTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTWdPLj0gbWVhbihNZ08pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldl82ID0gc2QoTWdPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDYU8uPSBtZWFuKENhTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzcgPSBzZChDYU8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5hMk8uID0gbWVhbihOYTJPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfOCA9IHNkKE5hMk8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEsyTy4gPSBtZWFuKEsyTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzkgPSBzZChLMk8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFAyTzUuID0gbWVhbihQMk81KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfMTAgPSBzZChQMk81KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUb3RhbC49bWVhbihUb3RhbCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzExID0gc2QoVG90YWwpKQ0KY2hlbV9zdW0gPC0gY2hlbV9zdW0gJT4lIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubnVtZXJpYyksIH4gcm91bmQoLiwgZGlnaXRzID0gMikpKQ0KY2hlbV9zdW0gJT4lIHJlbmFtZShsYXllciA9IGlkLCBuID0gY291bnQgLCBTaU8yID0gU2lPMi4sIHNkMSA9IGRldl8xLCBUaU8yID0gVGlPMi4gLCBzZDIgPSBkZXZfMikNCg0KZ3QoY2hlbV9zdW0pDQpgYGANCg0KDQojIyBNYWtlIFRBUyBjYWxjdWxhdGlvbnMNCg0KVG8gY2FsY3VsYXRlIGZvciB0aGUgVEFTIHBsb3QgdGhlIGRhdGEgcmVxdWlyZSBub3JtYWxpc2F0aW9uIG9mIHRoZSBkYXRhLiBUaGUgcmVzdCBvZiB0aGUgc2NyaXB0IHVzZXMgdW5ub3JtYWxpc2VkIGRhdGEgZm9yIHBsb3R0aW5nLCBidXQgdGhlIGNvZGUgYmVsb3cgY2FuIGJlIHVzZWQgdG8gbm9ybWFsaXNlIG90aGVyIGRhdGEgYWxzbyBieSByZXBsYWNpbmcgdGhlIGVsZW1lbnQgdG8gYmUgbm9ybWFsaXNlLg0KDQpgYGB7cn0NClRBU194IDwtICgxMDAvIGNoZW0gW1siVG90YWwiXV0pICogY2hlbSBbWyJTaU8yIl1dDQpUQVNfeSA8LSAoMTAwLyBjaGVtIFtbIlRvdGFsIl1dKSAqIChjaGVtIFtbIksyTyJdXSArIGNoZW0gW1siTmEyTyJdXSkNCg0KY2hlbSA8LSBjYmluZChjaGVtLCBUQVNfeCwgVEFTX3kpDQpgYGANCg0KIyBGaWx0ZXJpbmcgbWl4ZWQgZGF0YXNldHMNCkl0IGlzIHBvc3NpYmxlIHlvdXIgZGF0YXNoZWV0IGNvbnRhaW5zIG11bHRpcGxlIHR5cGVzIG9mIHRlcGhyYSB3aGljaCB3b3VsZCBiZW5lZml0IGZyb20gZmlsdGVyaW5nIGJlZm9yZSBwbG90dGluZy4gSSBzdWdnZXN0IHRoaXMgaXMgY2FycmllZCBvdXQgYnkgdXNpbmcgc2lsaWNhIHZhbHVlcyBhcyBhIGRpdmlzb3IuIFJoeW9saXRlcyA+NjklIHNpbGljYSBpcyBhIGNhc2UgZm9yIHRoaXMuIEhvd2V2ZXIsIGl0IG1pZ2h0IGJlIHdvcnRoIHBsb3R0aW5nIGV2ZXJ5dGhpbmcgZmlyc3QgYmVmb3JlIHRoZW4gc2VsZWN0aW5nIGEgZmlsdGVyIHRvIGVuc3VyZSB2aXRhbCBkYXRhIGlzIG5vdCBiZWluZyBleGNsdWRlZC4NCmBgYHtyfQ0KY2hlbSA8LSBmaWx0ZXIoY2hlbSwgU2lPMiA+NjgpDQpgYGANCg0KDQoNCiMgUGxvdHRpbmcgdGhlIGRhdGENCg0KRmlyc3Qgd2UgZ2VuZXJhdGUgYSBzZXJpZXMgb2YgcGxvdHMgZnJvbSBhbGwgcG9zc2libGUgcGFpcnMgb2YgZWxlbWVudHMuDQoNCmBgYHtyfQ0KcDEgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gVEFTX3gsIHkgPSBUQVNfeSwgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAyIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFNpTzIsIHkgPSBUaU8yLCBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDMgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gU2lPMiwgeSA9IEFsMk8zLCBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDQgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gU2lPMiwgeSA9IEZlTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwNSA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBTaU8yLCB5ID0gTW5PLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnA2IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFNpTzIsIHkgPSBNZ08sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDcgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gU2lPMiwgeSA9IENhTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwOCA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBTaU8yLCB5ID0gTmEyTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwOSA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBTaU8yLCB5ID0gSzJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnA0NyA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBTaU8yLCB5ID0gSzJPLCBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDEwIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFNpTzIsIHkgPSBQMk81LCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAxMSA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBUaU8yLCB5ID0gQWwyTzMsICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDEyIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFRpTzIsIHkgPSBGZU8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDEzIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFRpTzIsIHkgPSBNbk8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDE0IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFRpTzIsIHkgPSBNZ08sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDE1IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFRpTzIsIHkgPSBDYU8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDE2IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IFRpTzIsIHkgPSBOYTJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAxNyA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBUaU8yLCB5ID0gSzJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAxOCA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBUaU8yLCB5ID0gUDJPNSwgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMTkgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gQWwyTzMsIHkgPSBGZU8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDIwIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IEFsMk8zLCB5ID0gTW5PLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAyMSA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBBbDJPMywgeSA9IE1nTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMjIgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gQWwyTzMsIHkgPSBDYU8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDIzIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IEFsMk8zLCB5ID0gTmEyTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMjQgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gQWwyTzMsIHkgPSBLMk8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDI1IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IEFsMk8zLCB5ID0gUDJPNSwgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMjYgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gRmVPLCB5ID0gTW5PLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAyNyA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBGZU8sIHkgPSBNZ08sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDI4IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IEZlTywgeSA9IENhTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMjkgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gRmVPLCB5ID0gTmEyTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMzAgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gRmVPLCB5ID0gSzJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAzMSA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBGZU8sIHkgPSBQMk81LCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAzMiA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBNbk8sIHkgPSBNZ08sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDMzIDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IE1uTywgeSA9IENhTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMzQgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gTW5PLCB5ID0gTmEyTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwMzUgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gTW5PLCB5ID0gSzJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAzNiA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBNbk8sIHkgPSBQMk81LCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAzNyA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBNZ08sIHkgPSBDYU8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDM4IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IE1nTywgeSA9IE5hMk8sICBmaWxsID0gaWQsIHNoYXBlID0gaWQpKQ0KcDM5IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IE1nTywgeSA9IEsyTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwNDAgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gTWdPLCB5ID0gUDJPNSwgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwNDEgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gQ2FPLCB5ID0gTmEyTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwNDIgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gQ2FPLCB5ID0gSzJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnA0MyA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBDYU8sIHkgPSBQMk81LCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnA0NCA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBOYTJPLCB5ID0gSzJPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnA0NSA8LSBnZ3Bsb3QoY2hlbSwgYWVzKHggPSBOYTJPLCB5ID0gUDJPNSwgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpwNDYgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gSzJPLCB5ID0gUDJPNSwgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpgYGANCg0KDQojIyBDdXN0b20gdGVwaHJhIHRoZW1lDQpUbyBlbnN1cmUgY29uc2lzdGVuY3kgYW5kIHRvIHByb3ZpZGUgYSBzaG9ydGN1dCBvZiBjb2RpbmcgaXQgZXZlcnl0aW1lIHdlIHNldCB1cFsgYSBjdXN0b20gdGVwaHJhIHBsb3R0aW5nIHRoZW1lLiBUaGlzIG1lYW5zIGFsbCBvZiBvdXIgcGxvdHMgd2lsbCBoYXZlIHRoZSBzYW1lIHNpemVkIGZvbnRzIGV0Yy4uLg0KDQoNCmBgYHtyfQ0KVGVwaHJhLnRoZW1lIDwtdGhlbWVfYncoKSt0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KHNpemU9MTYpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9MTYpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQueT1lbGVtZW50X3RleHQoc2l6ZT0xNikpKw0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCANCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSkNCmBgYA0KDQojIyBDdXN0b20gY29sb3VyIHBhbGV0dGUNCg0KVGhlIGhleCBudW1iZXJzIGJlbG93IHNwZWNpZnkgYSBjdXN0b20gY29sb3VyIHBhbGV0dGUgZm9yIHBsb3R0aW5nLiBUaGVzZSBjYW4gYmUgYWx0ZXJlZCBidXQgd2VyZSBzbGVjdGVkIGluIG9yZGVyIHRvIGhlbHAgdGhvc2Ugd2l0aCBjb2xvdXIgdmlzaW9uIGRlZmljaWVuY2llcywgYW5kIHRoaXMgc2hvdWxkIGJlIGNvbnNpZGVyZWQgd2hlbiBtYWtpbmcgY2hhbmdlcy4gQXQgcHJlc2VudCAzNSBsYXllcnMgY2FuIGJlIHBsb3R0ZWQgdXNpbmcgdGhpcyBwYWxsZXRlLiBJZiB5b3UgaGF2ZSBtb3JlIHRoYW4gMzUgZ3JvdXBzIG9mIGRhdGEgeW91IHdpbGwgZWl0aGVyIGhhdmUgdG8gc3BlY2lmeSBhZGRpdGlvbmFsIGNvbG91cnMgb3IgY29uc2lkZXIgc3BsaXR0aW5nIHlvdXIgZGF0YXNldC4gVGhlIGxhdHRlciBtaWdodCBiZSBtb3JlIGFwcHJvcHJpYXRlIGZvciBpbXByb3ZpbmcgdGhlIGZpbmFsIGNsYXJpdHkgaW4gdGhlIHBsb3RzLiANCg0KYGBge3J9DQpjaGVtcGFsZXR0ZSA8LSBjKCIjMjA5QTI0IiwiI0E3NjlFRSIsIiNCNEM0MjgiLCIjZTMwMzAzIiwiIzAwMDAwMCIsIiNFRjEzOUQiLCIjM0E3MDBGIiwiIzUyODhGRiIsIiNFNjQ3MDEiLCIjN0Y5QUY1IiwiI0YzNkQyMCIsIiMwQjMwNzUiLCIjQzE4NTIyIiwiIzk2MzRBNiIsIiMxRDdENDYiLCIjODBkZGI4IiwiIzdDQkM5MiIsIiNCMTBFODkiLCIjMzg0QjI3IiwiI0Y4OTZGRCIsIiNDNkE3NjYiLCIjMjA2MjhFIiwiIzlDMDMyMyIsIiNDM0FGRTAiLCIjNTcyRDI0IiwiI0ZGNzlBMiIsIiMzRTZENkYiLCIjRTE4QzYzIiwiIzZGMkI0MCIsIiNERjlGQjQiLCAiIzI5MTcwMCIsICIjN2UwMDViIiwgIiMwMDU5N2EiICwgIiM3YjAwM2EiLAkiIzQ3MDYwMCIpDQpgYGANCg0KVGhlIHBhbGV0dGUgaXMga25vd24gYXMgImNoZW1wYWxldHRlIi4NCg0KIyBGaWd1cmVzIHsudGFic2V0IC50YWJzZXQtcGlsbHN9DQoNCldlIGZpcnN0IGdlbmVyYXRlIHRoZSBzaW1wbGUgYmktcGxvdHMgb2YgZWFjaCBlbGVtZW50LiBUaGlzIGluaXRpYWwgZXhwbG9yYXRpdmUgYXBwcm9hY2ggZmFjaWxpdGF0ZXMgZGF0YSBjaGVja2luZyBmb3IgdW51c3VhbCBhbmFseXNlcyBhbmQgcGVybWl0cyB0aGUgaWRlbnRpZmljYXRpb24gb2YgZWxlbWVudHMgd2l0aCBzaWduaWZpY2FudCB2YXJpYWJpbGl0eS4NCg0KIyMgVEFTIHBsb3QgTGUgTWFpdHJlIGV0IGFsLiAoMjAwMikNCmBgYHtyIFRBUyBwbG90LCBlY2hvPUZBTFNFfQ0KcDEgPC0gcDEgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkgKw0KICAjeGxhYihleHByZXNzaW9uIChTaU9bMl1+Iih3dCUpIikpICsgdXNlIHRoZXNlIGZvciBvdXRwdXR0aW5nIHN1YnNjcmlwdCBjaGFyYWN0ZXJzIGZvciBzYXZlZCBzdmcgb3IgcGRmIHBsb3RzLg0KICB4bGFiKCJTaU8yICh3dCUpIikgKw0KICAjeWxhYihleHByZXNzaW9uIChOYVsyXSpPfiIrIn5LWzJdKk9+Iih3dCUpIikpICsNCiAgeWxhYigiTmEyTyArIEsyTyAod3QlKSIpICsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKyANCiAgZ2VvbV9zZWdtZW50KHg9NzcseT0wLHhlbmQ9NjkseWVuZD04KSsgDQogIGdlb21fc2VnbWVudCh4PTY5LCB5PTgseGVuZD02OSx5ZW5kPTEzKStnZW9tX3NlZ21lbnQoeD00MSwgeT03LHhlbmQ9NTIuNSx5ZW5kPTE0KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTIuNSx5PTE0LHhlbmQ9NTcuNix5ZW5kPTExLjcpKw0KICBnZW9tX3NlZ21lbnQoeD00NSx5PTAseGVuZD00NSx5ZW5kPTUpKw0KICBnZW9tX3NlZ21lbnQoeD00NSx5PTUseGVuZD02Myx5ZW5kPTE0LjU2KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTIseT0wLHhlbmQ9NTIseWVuZD01KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTIseT01LHhlbmQ9NjMseWVuZD03KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTcseT0wLHhlbmQ9NTcseWVuZD01LjkpKw0KICBnZW9tX3NlZ21lbnQoeD02Myx5PTAseGVuZD02Myx5ZW5kPTcpKw0KICBnZW9tX3NlZ21lbnQoeD00NSx5PTUseGVuZD01Mix5ZW5kPTUpKw0KICBnZW9tX3NlZ21lbnQoeD01Mix5PTUseGVuZD00OS40LHllbmQ9Ny4zKSsNCiAgZ2VvbV9zZWdtZW50KHg9NTcseT01LjkseGVuZD01Myx5ZW5kPTkuMykrDQogIGdlb21fc2VnbWVudCh4PTYzLHk9Nyx4ZW5kPTU3LjYseWVuZD0xMS43KSsNCiAgZ2VvbV9zZWdtZW50KHg9NDkuNCx5PTcuMyx4ZW5kPTQ1LHllbmQ9OS40KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTMseT05LjMseGVuZD00OC40LHllbmQ9MTEuNSkrDQogIGdlb21fc2VnbWVudCh4PTQxLHk9MCx4ZW5kPTQxLHllbmQ9NykrDQogIGdlb21fc2VnbWVudCh4PTUyLjUseT0xNCx4ZW5kPTQ5LHllbmQ9MTUuNSkrDQogIGdlb21fc2VnbWVudCh4PTQxLHk9Myx4ZW5kPTQ1LHllbmQ9MykrDQogIGdlb21fc2VnbWVudCh4PTYzLHk9Nyx4ZW5kPTY5LHllbmQ9OCkrDQogIHNjYWxlX3hfY29udGludW91cyhsaW1pdHM9Yyg0MCwgODApLCBleHBhbmQgPSBjKDAsIDApKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoMCwgMTYpLCBleHBhbmQgPSBjKDAsIDApKSArDQogIGFubm90YXRlKCJ0ZXh0IiwgeCA9IGMoNzYsNjcuNSw1OSw1NCw0OCw0Mi41LDQ4LjUsNTMsNTcsNjMsNDMsNDgsNTMsNTcsNDIpLCB5ID0gYyg2LDUuMiw0LDMsMi41LDEuNSw2LDcuNSw4LjgsMTEsNywxMCwxMiwxNC41LDEzKSwgbGFiZWwgPSBjKCJSIiwiTzMiLCJPMiIsIk8xIiwiQiIsIlBjIiwiUzEiLCJTMiIsIlMzIiwiVCIsIlUxIiwiVTIiLCJVMyIsIlBoIiwiRiIpKSArDQogIFRlcGhyYS50aGVtZQ0KcDENCmBgYA0KDQojIyBTaU8yIFZTIFRpTzINCmBgYHtyIGVjaG89RkFMU0V9DQpwMiA8LSBwMiArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJTaU8yICh3dCUpIikreWxhYigiVGlPMiAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAyDQpgYGANCg0KIyMgU2lPMiBWUyBBbDJPMw0KYGBge3IgZWNobz1GQUxTRX0NCnAzIDwtIHAzICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlNpTzIgKHd0JSkiKSt5bGFiKCJBbDJPMyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAzDQpgYGANCg0KIyMgU2lPMiBWUyBGZU8NCmBgYHtyIGVjaG89RkFMU0V9DQpwNCA8LSBwNCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJTaU8yICh3dCUpIikreWxhYigiRmVPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDQNCmBgYA0KDQojIyBTaU8yIFZTIE1uTw0KYGBge3IgZWNobz1GQUxTRX0NCnA1IDwtIHA1ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlNpTzIgKHd0JSkiKSt5bGFiKCJNbk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwNQ0KYGBgDQoNCiMjIFNpTzIgVlMgTWdPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDYgPC0gcDYgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiU2lPMiAod3QlKSIpK3lsYWIoIk1nTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnA2DQpgYGANCg0KIyMgU2lPMiBWUyBDYU8NCmBgYHtyIGVjaG89RkFMU0V9DQpwNyA8LSBwNyArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJTaU8yICh3dCUpIikreWxhYigiQ2FPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDcNCmBgYA0KDQojIyBTaU8yIFZTIE5hMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwOCA8LSBwOCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJTaU8yICh3dCUpIikreWxhYigiTmEyTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnA4DQpgYGANCg0KIyMgU2lPMiBWUyBLMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwOSA8LSBwOSArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJTaU8yICh3dCUpIikreWxhYigiSzJPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDQ3IDwtIHA0NyArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSsNCiAgeGxhYigiU2lPMiAod3QlKSIpK3lsYWIoIksyTyAod3QlKSIpKw0KICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgZ2VvbV9zZWdtZW50KHg9NDgseT0xLjYseGVuZD01Mix5ZW5kPTIuNCkrIA0KICBnZW9tX3NlZ21lbnQoeD01MiwgeT0yLjQseGVuZD01Nix5ZW5kPTMuMikrDQogIGdlb21fc2VnbWVudCh4PTU2LCB5PTMuMix4ZW5kPTYzLHllbmQ9NC4wKSsNCiAgZ2VvbV9zZWdtZW50KHg9NDgseT0xLjIseGVuZD01Mix5ZW5kPTEuNSkrDQogIGdlb21fc2VnbWVudCh4PTUyLHk9MS41LHhlbmQ9NTYseWVuZD0xLjgpKw0KICBnZW9tX3NlZ21lbnQoeD01Nix5PTEuOCx4ZW5kPTYzLHllbmQ9Mi40KSsNCiAgZ2VvbV9zZWdtZW50KHg9NjMseT0yLjQseGVuZD03MCx5ZW5kPTMuMCkrDQogIGdlb21fc2VnbWVudCh4PTQ4LHk9MC4zLHhlbmQ9NTIseWVuZD0wLjUpKw0KICBnZW9tX3NlZ21lbnQoeD01Mix5PTAuNSx4ZW5kPTU2LHllbmQ9MC43KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTYseT0wLjcseGVuZD02Myx5ZW5kPTEuMCkrDQogIGdlb21fc2VnbWVudCh4PTYzLHk9MS4wLHhlbmQ9NzAseWVuZD0xLjMpKw0KICBnZW9tX3NlZ21lbnQoeD03MCx5PTEuMyx4ZW5kPTgwLHllbmQ9MS42KSsNCiAgVGVwaHJhLnRoZW1lDQpwNDcNCmBgYA0KDQojIyBTaU8yIFZTIFAyTzUNCmBgYHtyIGVjaG89RkFMU0V9DQpwMTAgPC0gcDEwICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlNpTzIgKHd0JSkiKSt5bGFiKCJQMk81ICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDEwDQpgYGANCg0KIyMgVGlPMiBWUyBBbDJPMw0KYGBge3IgZWNobz1GQUxTRX0NCnAxMSA8LSBwMTEgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiVGlPMiAod3QlKSIpK3lsYWIoIkFsMk8zICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDExDQpgYGANCg0KIyMgVGlPMiB2cyBGZU8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMTIgPC0gcDEyICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlRpTzIgKHd0JSkiKSt5bGFiKCJGZU8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMTINCmBgYA0KDQojIyBUaU8yIHZzIE1uTw0KYGBge3IgZWNobz1GQUxTRX0NCnAxMyA8LSBwMTMgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiVGlPMiAod3QlKSIpK3lsYWIoIk1uTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAxMw0KYGBgDQoNCiMjIFRpTzIgVlMgTWdPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDE0IDwtIHAxNCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJUaU8yICh3dCUpIikreWxhYigiTWdPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDE0DQpgYGANCg0KIyMgVGlPMiBWUyBDYU8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMTUgPC0gcDE1ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlRpTzIgKHd0JSkiKSt5bGFiKCJDYU8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMTUNCmBgYA0KDQojIyBUaU8yIFZTIE5hMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMTYgPC0gcDE2ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlRpTzIgKHd0JSkiKSt5bGFiKCJOYTJPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDE2DQpgYGANCg0KIyMgVGlPMiBWUyBLMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMTcgPC0gcDE3ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlRpTzIgKHd0JSkiKSt5bGFiKCJLMk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMTcNCmBgYA0KDQojIyBUaU8yIFZTIFAyTzUNCmBgYHtyIGVjaG89RkFMU0V9DQpwMTggPC0gcDE4ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIlRpTzIgKHd0JSkiKSt5bGFiKCJQMk81ICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDE4DQpgYGANCg0KIyMgQWwyTzMgVlMgRmVPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDE5IDwtIHAxOSArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJBbDJPMyAod3QlKSIpK3lsYWIoIkZlTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAxOQ0KYGBgDQoNCiMjIEFsMk8zIFZTIE1uTw0KYGBge3IgZWNobz1GQUxTRX0NCnAyMCA8LSBwMjAgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiQWwyTzMgKHd0JSkiKSt5bGFiKCJNbk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMjANCmBgYA0KDQojIyBBbDJPMyBWUyBNZ08NCmBgYHtyfQ0KcDIxIDwtIHAyMSArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJBbDJPMyAod3QlKSIpK3lsYWIoIk1nTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAyMQ0KYGBgDQoNCiMjIEFsMk8zIFZTIENhTw0KYGBge3IgZWNobz1GQUxTRX0NCnAyMiA8LSBwMjIgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiQWwyTzMgKHd0JSkiKSt5bGFiKCJDYU8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMjINCmBgYA0KDQojIyBBbDJPMyBWUyBOYTJPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDIzIDwtIHAyMyArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJBbDJPMyAod3QlKSIpK3lsYWIoIk5hMk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMjMNCmBgYA0KDQojIyBBbDJPMyBWUyBLMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMjQgPC0gcDI0ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIkFsMk8zICh3dCUpIikreWxhYigiSzJPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDI0DQpgYGANCg0KIyMgQWwyTzMgVlMgUDJPNQ0KYGBge3IgZWNobz1GQUxTRX0NCnAyNSA8LSBwMjUgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiQWwyTzMgKHd0JSkiKSt5bGFiKCJQMk81ICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDI1DQpgYGANCg0KIyMgRmVPIFZTIE1uTw0KYGBge3IgZWNobz1GQUxTRX0NCnAyNiA8LSBwMjYgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiRmVPICh3dCUpIikreWxhYigiTW5PICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDI2DQpgYGANCg0KIyMgRmVPIHZzIE1nTw0KYGBge3IgZWNobz1GQUxTRX0NCnAyNyA8LSBwMjcgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiRmVPICh3dCUpIikreWxhYigiTWdPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDI3DQpgYGANCg0KIyMgRmVPIHZzIENhTw0KYGBge3IgZWNobz1GQUxTRX0NCnAyOCA8LSBwMjggKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiRmVPICh3dCUpIikreWxhYigiQ2FPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDI4DQpgYGANCg0KIyMgRmVPIFZTIE5hMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMjkgPC0gcDI5ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIkZlTyAod3QlKSIpK3lsYWIoIk5hMk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMjkNCmBgYA0KDQojIyBGZU8gVlMgSzJPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDMwIDwtIHAzMCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJGZU8gKHd0JSkiKSt5bGFiKCJLMk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMzANCmBgYA0KDQojIyBGZU8gVlMgUDJPNQ0KYGBge3IgZWNobz1GQUxTRX0NCnAzMSA8LSBwMzEgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiRmVPICh3dCUpIikreWxhYigiUDJPNSAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAzMQ0KYGBgDQoNCiMjIE1uTyBWUyBNZ08NCmBgYHtyIGVjaG89RkFMU0V9DQpwMzIgPC0gcDMyICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIk1uTyAod3QlKSIpK3lsYWIoIk1nTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAzMg0KYGBgDQoNCiMjIE1uTyBWUyBDYU8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMzMgPC0gcDMzICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIk1uTyAod3QlKSIpK3lsYWIoIkNhTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAzMw0KYGBgDQoNCiMjIE1uTyBWUyBOYTJPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDM0IDwtIHAzNCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJNbk8gKHd0JSkiKSt5bGFiKCJOYTJPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDM0DQpgYGANCg0KIyMgTW5PIFZTIEsyTw0KYGBge3IgZWNobz1GQUxTRX0NCnAzNSA8LSBwMzUgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiTW5PICh3dCUpIikreWxhYigiSzJPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDM1DQpgYGANCg0KIyMgTW5PIFZTIFAyTzUNCmBgYHtyIGVjaG89RkFMU0V9DQpwMzYgPC0gcDM2ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIk1uTyAod3QlKSIpK3lsYWIoIlAyTzUgKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMzYNCmBgYA0KDQojIyBNZ08gVlMgQ2FPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDM3IDwtIHAzNyArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJNZ08gKHd0JSkiKSt5bGFiKCJDYU8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwMzcNCmBgYA0KDQojIyBNZ08gVlMgTmEyTw0KYGBge3IgZWNobz1GQUxTRX0NCnAzOCA8LSBwMzggKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiTWdPICh3dCUpIikreWxhYigiTmEyTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAzOA0KYGBgDQoNCiMjIE1nTyBWUyBLMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwMzkgPC0gcDM5ICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIk1nTyAod3QlKSIpK3lsYWIoIksyTyAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnAzOQ0KYGBgDQoNCiMjIE1nTyBWUyBQMk81DQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDQwIDwtIHA0MCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJNZ08gKHd0JSkiKSt5bGFiKCJQMk81ICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDQwDQpgYGANCg0KIyMgQ2FPIFZTIE5hMk8NCmBgYHtyIGVjaG89RkFMU0V9DQpwNDEgPC0gcDQxICsgZ2VvbV9wb2ludChhZXMoZmlsbCA9IGlkKSwgc2l6ZT00LCBhbHBoYT0wLjgpK3hsYWIoIkNhTyAod3QlKSIpK3lsYWIoIk5hMk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwNDENCmBgYA0KDQojIyBDYU8gVlMgSzJPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDQyIDwtIHA0MiArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJDYU8gKHd0JSkiKSt5bGFiKCJLMk8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lDQpwNDINCmBgYA0KDQojIyBDYU8gVlMgUDJPNQ0KYGBge3IgZWNobz1GQUxTRX0NCnA0MyA8LSBwNDMgKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiQ2FPICh3dCUpIikreWxhYigiUDJPNSAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnA0Mw0KYGBgDQoNCiMjIE5hMk8gVlMgSzJPDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDQ0IDwtIHA0NCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJOYTJPICh3dCUpIikreWxhYigiSzJPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDQ0DQpgYGANCg0KIyMgTmEyTyBWUyBQMk81DQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDQ1IDwtIHA0NSArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJOYTJPICh3dCUpIikreWxhYigiUDJPNSAod3QlKSIpK3NjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9YygyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSkpKw0KICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBUZXBocmEudGhlbWUNCnA0NQ0KYGBgDQoNCiMjIEsyTyBWUyBQMk81DQpgYGB7ciBlY2hvPUZBTFNFfQ0KcDQ2IDwtIHA0NiArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJLMk8gKHd0JSkiKSt5bGFiKCJQMk81ICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KcDQ2DQpgYGANCiMgey19DQoNCiMgU2F2aW5nIGluZGl2aWR1YWwgcGxvdHMNCg0KV2UgcHJvcG9zZSBleHBvcnRpbmcgeW91ciBwbG90cyBpbiAuc3ZnIGZvcm1hdC4gVGhpcyBpcyBhIHZlY3RvciBmaWxlIGZvcm1hdCB0aGF0IHByZXNlcnZlcyB5b3VyIGRhdGEgd2l0aG91dCBzaXplIGFuZCBzY2FsaW5nIGlzc3Vlcy4gSXQgaXMgYWxzbyByZWFkYWJsZSBhbmQgZWRpdGFibGUgYnkgc29mdHdhcmUgbGlrZSBBZG9iZSBJbGx1c3RyYXRvciwgQWZmaW5pdHkgRGVzaWduZXIsIG9yIGZyZWUgYWx0ZXJuYXRpdmVzIGxpa2UgSW5rc2NhcGUuIC5Vc2luZyB0aGUgZmlsZSBzdHJ1Y3R1cmUgcHJlc2VudGVkIGhlcmUgdGhlIGFsbCBwbG90cyBjYW4gYmUgbmFtZWQgYXBwcm9wcmlhdGVseSBhbmQgd2lsbCBiZSBzYXZlZCBpbiB0aGUgT3V0cHV0IC0+IFBsb3RzIGZvbGRlci4gVGhlIHdpZHRoIGFuZCBoZWlnaHQgYW5kIGRwaSBvdXRwdXRzIGNhbiBiZSBhbHRlcmVkIGJ1dCBvdmVycmlkZSB0aGUgcHJldmlldyBmdW5jdGlvbnMgaW4gUnN0dWRpbyBhbmQgd2UgcmVjb21tZW5kIHRoYXQgeW91IHZpZXcgdGhlIHN2ZyBmaWxlIGRpcmVjdGx5IGluIHlvdSBwcmVmZXJyZWQgaW1hZ2UgZWRpdG9yIHRvIHVuZGVyc3RhbmQgaG93IGl0IG1pZ2h0IGxvb2suDQoNCmBgYHtyfQ0KZ2dzYXZlKCBmaWxlbmFtZSA9IGZpbGUucGF0aCgiU2NyaXB0IiwgIk91dHB1dCIsIlBsb3RzIiwiZmlnMS5zdmciKSwgcGxvdCA9IHAxLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA2LCBkcGkgPSAzMDApDQpgYGANCg0KIyBNdWx0aXZhcmlhdGUgYW5hbHlzaXMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCk11bHRpdmFyaWF0ZSBhbmFseXNpcyB2aWEgb3JkaW5hdGlvbiBpcyBvZnRlbiBhIGhlbHBmdWwgd2F5IG9mIGV4cGxvcmluZyB5b3VyIGRhdGEuIEl0IHBlcm1pdHMgdGhlIGlkZW50aWZpY2F0aW9uIG9mIHVzZWZ1bCBlbGVtZW50cyBmb3IgZGlzY3JpbWluYXRpb24gYW5kIGZhY2lsaXRhdGVzIGRpbWVuc2lvbiByZWR1Y3Rpb24uIFVuZm9ydHVuYXRlbHksIHBlcmNlbnRhZ2UgZGF0YSBjYW4gaGF2ZSBwcm9ibGVtYXRpYyBjb3ZhcmlhdGlvbiBhbmQgc2hvdWxkIGJlICdmcmVlZCcgZnJvbSB0aGVpciBjb21wb3NpdGlvbmFsIHN1bSB3aGVyZSBwb3NzaWJsZS4gVGhpcyBjYW4gYmUgYWNoaWV2ZWQgdmlhIHVuZGVydGFraW5nIGEgY2VudHJlZCBsb2ctcmF0aW8gdHJhbnNmb3JtLg0KDQojIyBjZW50cmVkIGxvZy1yYXRpbyBkYXRhIHRhYmxlDQpgYGB7cn0NCmNoZW1fbXVsdGkgPC0gY2hlbVsgLWMoMSw2LDExLDEyKV0gIyMgY2hlY2sgY29sdW1ucyB0byBkcm9wLiBDdXJyZW50bHkgZHJvcHBpbmcgaWQsIE1uTywgUDJPNSwgYW5kIFRvdGFsIHRvIHBlcmZvcm0gdGhlIGNsciB0cmFuc2Zvcm0uDQpjaGVtX211bHRpW2lzLm5hKGNoZW1fbXVsdGkpXSA8LSAwLjAwNSAjIHJlcGxhY2UgTkFzIHdpdGggaGFsZiB0aGUgZGV0ZWN0aW9uIGxpbWl0DQpjaGVtX211bHRpX2NsciA8LSBjbHIoY2hlbV9tdWx0aSkNCmNtY2xyIDwtIGFzLmRhdGEuZnJhbWUoY2hlbV9tdWx0aV9jbHIpDQpoZWFkKGNtY2xyKQ0KYGBgDQoNCldlIGNhbiBzdW1tYXJpc2UgdGhlIGltcG9ydGFuY2Ugb2YgdGhlIHJlc3VsdGluZyBwcmluY2lwYWwgY29tcG9uZW50cyBieSBzdW1tYXJpemluZyBob3cgbXVjaCBvZiB0aGUgdG90YWwgdmFyaWFuY2UgaXMgY2FwdHVyZWQgYnkgZWFjaCBwcmluY2lwYWwgY29tcG9uZW50Lg0KDQojIyBQQ0Egc3VtbWFyeQ0KYGBge3IgZWNobz1GQUxTRX0NCnBjYXNjb3JlcyA8LSBwcmNvbXAoY21jbHIpDQpzdW1tIDwtIGFzLmRhdGEuZnJhbWUoc3VtbWFyeShwY2FzY29yZXMpJGltcG9ydGFuY2UpDQpzdW1tIDwtIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKHN1bW0sICJJbmZvcm1hdGlvbiIpDQpzdW1tICU+JSBndCgpDQpgYGANCklmIHRoaXMgaGFzIGNhcHR1cmVkIGEgc2lnbmlmaWNhbnQgYW1vdW50IG9mIHZhcmlhdGlvbiBpdCB3b3VsZCBiZSB3b3J0aCBwbG90dGluZyB0aGUgb3V0cHV0IGluIG9yZGVyIHRvIGlkZW50aWZ5IHRoZSBpbXBvcnRhbnQgdmFyaWFibGVzIGluIGRldGVybWluaW5nIHRoZSBjaGFuZ2VzIG9ic2VydmVkLg0KDQojIyBQQ0Egc2NvcmVzIHNjcmVlIHBsb3QNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1GQUxTRX0NCmZ2aXpfZWlnKHBjYXNjb3JlcykNCg0KYGBgDQoNClRoaXMgaXMgYSB2aXN1YWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIHN1bW1hcnkgdGFibGUgc2hvd2luZyB0aGUgcGVyY2VudGFnZSBvZiB0aGUgdG90YWwgdmFyaWFuY2UgZXhwbGFpbmVkIGJ5IGVhY2ggZGltZW5zaW9uLg0KDQojIyBWYXJpYWJsZXMgUENBIHBsb3QNCmBgYHtyIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1GQUxTRX0NCmZ2aXpfcGNhX3ZhcihwY2FzY29yZXMsIGNvbC52YXIgPSAiY29udHJpYiIsICMgQ29sb3IgYnkgY29udHJpYnV0aW9ucyB0byB0aGUgUEMNCiAgICAgICAgICAgICBncmFkaWVudC5jb2xzID0gYygiIzAwQUZCQiIsICIjRTdCODAwIiwgIiNGQzRFMDciKSwNCiAgICAgICAgICAgICByZXBlbCA9IFRSVUUgICAgICMgQXZvaWQgdGV4dCBvdmVybGFwcGluZw0KKQ0KYGBgDQoNCg0KIyMgTG9hZGluZ3MgZGltZW5zaW9uIDENCmBgYHtyIGVjaG89RkFMU0V9DQpmdml6X2NvbnRyaWIocGNhc2NvcmVzLCBjaG9pY2U9InZhciIsIGF4ZXMgPSAxLGZpbGwgPSAiIzAwQUZCQiIsIGNvbG9yID0gImJsYWNrIikgK3RoZW1lX21pbmltYWwoKSArdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUpKQ0KYGBgDQoNCiMjIExvYWRpbmdzIGRpbWVuc2lvbiAyDQoNCmBgYHtyIGVjaG89RkFMU0V9DQpmdml6X2NvbnRyaWIocGNhc2NvcmVzLCBjaG9pY2U9InZhciIsIGF4ZXMgPSAyLGZpbGwgPSAiIzAwQUZCQiIsIGNvbG9yID0gImJsYWNrIikgK3RoZW1lX21pbmltYWwoKSArdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGU9NDUpKQ0KYGBgDQoNCiMjIFBDQSAtIEJpcGxvdA0KYGBge3Igd2FybmluZyA9IEZBTFNFLCBlY2hvPUZBTFNFfQ0KZnZpel9wY2FfYmlwbG90KHBjYXNjb3JlcywgcmVwZWwgPSBGQUxTRSwNCiAgICAgICAgICAgICAgICBjb2wudmFyID0gIiMyRTlGREYiLCAjIFZhcmlhYmxlcyBjb2xvcg0KICAgICAgICAgICAgICAgIGNvbC5pbmQgPSAiIzY5Njk2OSIgICMgSW5kaXZpZHVhbHMgY29sb3INCikNCmBgYA0KDQojIyBQQ0EgLSBncm91cGVkDQpgYGB7ciB3YXJuaW5nID0gRkFMU0UsIGVjaG89RkFMU0V9DQpwY291dCA8LSBwY2FzY29yZXMkeA0KaWQgPC0gYXMuZGF0YS5mcmFtZShjaGVtJGlkKQ0KaWQgPC0gdW5saXN0KGlkKQ0KaWQgPC0gYXNfZGF0YV9mcmFtZShpZCkNCnBjb3V0IDwtIGNiaW5kKGlkLCBwY291dCkNCmNvbG5hbWVzKHBjb3V0KVtjb2xuYW1lcyhwY291dCk9PSJ2YWx1ZSJdIDwtICJpZCINCnBjMXBsb3QgPC0gZ2dwbG90KHBjb3V0LCBhZXMoeCA9IFBDMSwgeSA9IFBDMiwgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnBjMXBsb3QgPC0gcGMxcGxvdCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJQQzEiKSt5bGFiKCJQQzIiKSt0aGVtZV9idygpK3RoZW1lKGF4aXMudGl0bGUueD1lbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoc2l6ZT0xNiksIGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChzaXplPTE2KSwgYXhpcy50ZXh0Lnk9ZWxlbWVudF90ZXh0KHNpemU9MTYpKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKStzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIHRoZW1lKHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkNCg0KICBwYzFwbG90DQpgYGANCg0KIyB7LX0NCg0KDQojIEludGVyYWN0aXZlIGZpZ3VyZXMgey50YWJzZXQgLnRhYnNldC1waWxsc30NCg0KVGhlIGZ1bmN0aW9uIGdncGxvdGx5IHdpdGhpbiB0aGUgcGxvdGx5IHBhY2thZ2UgaXMgZXh0cmVtZWx5IHVzZWZ1bCBmb3IgaW50ZXJhY3RpdmVseSBleGFtaW5pbmcgZGF0YS4gZ2dwbG90bHkgcGxvdHMgYWxsb3cgeW91IHRvIHpvb20gaW50byBhcmVhcyBvZiBpbnRlcmVzdCBhbmQgdHVybiBsYXllcnMgb24gYW5kIG9mZiBhcyB3ZWxsIGFzIHNhdmluZyBsb3cgcmVzb2x1dGlvbiAucG5nIGZpbGVzIG9mIHpvb21lZCBzZWN0aW9ucyBvZiB5b3VyIHBsb3RzLldlIHJlZmVyIHRvIHRoZXNlIGFzIGlQbG90cyBpbiBvcmRlciB0byBkaXN0aW5ndWlzaCB0aGVtIGZyb20gc3RhdGljIHBsb3RzIHByZXNlbnRlZCBhYm92ZS4NCg0KIyMgaVRBUyBwbG90DQpgYGB7ciB3YXJuaW5nID0gRkFMU0UsIGVjaG89RkFMU0V9DQpnZ3Bsb3RseShwMSwgd2lkdGggPSAxMDAwLCBoZWlnaHQgPSA4MDApDQpgYGANCg0KIyMgaUZlTy1DYU8NCmBgYHtyIHdhcm5pbmcgPSBGQUxTRSwgZWNobz1GQUxTRX0NCmdncGxvdGx5KHAyOCwgd2lkdGggPSAxMDAwLCBoZWlnaHQgPSA4MDApDQpgYGANCiMjIGlLLWxpbmVzDQpgYGB7ciB3YXJuaW5nID0gRkFMU0UsIGVjaG89RkFMU0V9DQpnZ3Bsb3RseShwNDcsIHdpZHRoID0gMTAwMCwgaGVpZ2h0ID0gODAwLCBkeW5hbWljVGlja3MgPSBUUlVFKQ0KYGBgDQojIyBpVGlPMiB2cyBBbDJPMw0KYGBge3Igd2FybmluZyA9IEZBTFNFLCBlY2hvPUZBTFNFfQ0KZ2dwbG90bHkocDExLCB3aWR0aCA9IDEwMDAsIGhlaWdodCA9IDgwMCwgZHluYW1pY1RpY2tzID0gVFJVRSkNCmBgYA0KDQoNCiMjIGlLMk8gdnMgQ2FPDQpgYGB7ciB3YXJuaW5nID0gRkFMU0UsIGVjaG89RkFMU0V9DQpnZ3Bsb3RseShwNDIsIHdpZHRoID0gMTAwMCwgaGVpZ2h0ID0gODAwLCBkeW5hbWljVGlja3MgPSBUUlVFKQ0KYGBgDQoNCg0KDQojIyB7LX0NCg0KIyBTYXZpbmcgYWxsIGZpZ3VyZXMgdG8gYSAucGRmDQpgYGB7cn0NCmwgPC0gbGlzdChwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBwNywgcDgsIHA5LCBwNDcsIHAxMCwgcDExLCBwMTIsIHAxMywgcDE0LCBwMTUsIHAxNiwgcDE3LCBwMTgsIHAxOSwgcDIwLCBwMjEsIHAyMiwgcDIzLCBwMjQsIHAyNSwgcDI2LCBwMjcsIHAyOCwgcDI5LCBwMzAsIHAzMSwgcDMyLCBwMzMsIHAzNCwgcDM1LCBwMzYsIHAzNywgcDM4LCBwMzksIHA0MCwgcDQxLCBwNDIsIHA0MywgcDQ0LCBwNDUsIHA0NikNCnBkZigiYWxscGxvdHNvdXQucGRmIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gNikNCmludmlzaWJsZShsYXBwbHkobCwgcHJpbnQpKQ0KZGV2Lm9mZigpDQpgYGANCg0KIyMgSGFya2VyIHBsb3QNCkl0IGlzIGZyZXF1ZW50bHkgdXNlZnVsIHRvIHBsb3QgYWxsIG9mIHRoZSBjb2xsZWN0ZWQgZWxlbWVudGFsIGRhdGEgYWdhaW5zdCBTaU9bMl0uIFRoaXMgcGVybWl0cyBhbiBhc3Nlc3NtZSB0b2YgZ3JvdXBpbmdzIHdpdGhpbiB0aGUgZGF0YSBhbmQgd2hpY2ggZWxlbWVudHMgbWlnaHQgYmUgdXNlZnVsIGRpc2NyaW1pbmF0b3JzLiBBZGRpdGlvbmFsbHksIHd0JSBLMk8gdnMgU2lPMiBjYW4gZnVydGhlciBjbGFzc2lmeSB0aGUgdGVwaHJhIHRvIGxvdywgbWlkIGFuZCBoaWdoIFBvdGFzc2l1bSB2YWx1ZXMuIFRoZSBkaXZpZGluZyBsaW5lcyBpbmNsdWRlZCBoZXJlIGFyZSBmcm9tIHh4eHh4eHh4Lg0KYGBge3IgZmlnLmhlaWdodCA9IDEwLCBmaWcud2lkdGggPSAxOH0NCmcxIDwtIHBsb3RfZ3JpZChwMSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiksIA0KICAgICAgICAgICAgICAgIHAyICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSwNCiAgICAgICAgICAgICAgICBwMyArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICAgICAgICAgICAgICAgIHA0ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksDQogICAgICAgICAgICAgICAgcDUgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwNCiAgICAgICAgICAgICAgICBwNiArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICAgICAgICAgICAgICAgIHA3ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksDQogICAgICAgICAgICAgICAgcDggKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgDQogICAgICAgICAgICAgICAgcDQ3ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIA0KICAgICAgICAgICAgICAgIHAxMCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLA0KICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIkEiLCAiQiIsICJDIiwgIkQiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIkoiKSwgYWxpZ24gPSAiYiIpDQpsZWdlbmQgPC0gZ2V0X2xlZ2VuZChwMSkNCmxlZ3Bsb3QgPC0gcGxvdF9ncmlkKGxlZ2VuZCkNCnB4IDwtIHBsb3RfZ3JpZCggZzEsIHJlbF93aWR0aHMgPSBjKDQsIDEpKQ0KbDIgPC0gbGlzdChweCxsZWdwbG90KQ0KcGRmKCJTY3JpcHQvT3V0cHV0L1Bsb3RzL0hhcmtlcnBsb3QucGRmIiwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gMjApDQppbnZpc2libGUobGFwcGx5KGwyLCBwcmludCkpDQpkZXYub2ZmKCkNCg0KZ2dzYXZlKCBmaWxlbmFtZSA9IGZpbGUucGF0aCgiU2NyaXB0IiwiT3V0cHV0IiwiUGxvdHMiLCJIYXJrZXIuc3ZnIiksIHBsb3QgPSBweCwgd2lkdGggPSAzMCwgaGVpZ2h0ID0gMjAsIGRwaSA9IDMwMCkNCg0KcHJpbnQoZzEpDQoNCmBgYA0KDQojIE90aGVyIHVzZWZ1bCBSIHRyaWNrcw0KIyMgQ3JlYXRpbmcgYW4gaW5zZXQgd2l0aGluIGEgZmlndXJlDQpgYGB7ciB3YXJuaW5nPUZBTFNFIH0NCnAxMDAgPC0gZ2dwbG90KGNoZW0sIGFlcyh4ID0gVEFTX3gsIHkgPSBUQVNfeSwgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnAxMDAgPC0gcDEwMCArIGdlb21fcG9pbnQoYWVzKGZpbGwgPSBpZCksIHNpemU9NCwgYWxwaGE9MC44KSt4bGFiKCJTaU8yICh3dCUpIikreWxhYigiTmEyTytLMk8gKHd0JSkiKSsNCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArZ2VvbV9zZWdtZW50KHg9NzcseT0wLHhlbmQ9NjkseWVuZD04KSsgDQogIGdlb21fc2VnbWVudCh4PTY5LCB5PTgseGVuZD02OSx5ZW5kPTEzKStnZW9tX3NlZ21lbnQoeD00MSwgeT03LHhlbmQ9NTIuNSx5ZW5kPTE0KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTIuNSx5PTE0LHhlbmQ9NTcuNix5ZW5kPTExLjcpK2dlb21fc2VnbWVudCh4PTQ1LHk9MCx4ZW5kPTQ1LHllbmQ9NSkrDQogIGdlb21fc2VnbWVudCh4PTQ1LHk9NSx4ZW5kPTYzLHllbmQ9MTQuNTYpK2dlb21fc2VnbWVudCh4PTUyLHk9MCx4ZW5kPTUyLHllbmQ9NSkrDQogIGdlb21fc2VnbWVudCh4PTUyLHk9NSx4ZW5kPTYzLHllbmQ9NykrZ2VvbV9zZWdtZW50KHg9NTcseT0wLHhlbmQ9NTcseWVuZD01LjkpKw0KICBnZW9tX3NlZ21lbnQoeD02Myx5PTAseGVuZD02Myx5ZW5kPTcpK2dlb21fc2VnbWVudCh4PTQ1LHk9NSx4ZW5kPTUyLHllbmQ9NSkrDQogIGdlb21fc2VnbWVudCh4PTUyLHk9NSx4ZW5kPTQ5LjQseWVuZD03LjMpK2dlb21fc2VnbWVudCh4PTU3LHk9NS45LHhlbmQ9NTMseWVuZD05LjMpKw0KICBnZW9tX3NlZ21lbnQoeD02Myx5PTcseGVuZD01Ny42LHllbmQ9MTEuNykrZ2VvbV9zZWdtZW50KHg9NDkuNCx5PTcuMyx4ZW5kPTQ1LHllbmQ9OS40KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTMseT05LjMseGVuZD00OC40LHllbmQ9MTEuNSkrZ2VvbV9zZWdtZW50KHg9NDEseT0wLHhlbmQ9NDEseWVuZD03KSsNCiAgZ2VvbV9zZWdtZW50KHg9NTIuNSx5PTE0LHhlbmQ9NDkseWVuZD0xNS41KStnZW9tX3NlZ21lbnQoeD00MSx5PTMseGVuZD00NSx5ZW5kPTMpKw0KICBnZW9tX3NlZ21lbnQoeD02Myx5PTcseGVuZD02OSx5ZW5kPTgpKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzPWMoNzQsIDc5KSwgZXhwYW5kID0gYygwLCAwKSkgKyAjIyBzZXQgeCBheGlzIG9mIGluc2VydA0KICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzPWMoNiwgMTAuNSksIGV4cGFuZCA9IGMoMCwgMCkpICsgIyMgc2V0IHkgYXhpcyBvZiBpbnNlcnQNCiAgdGhlbWVfYncoKSt0aGVtZShheGlzLnRpdGxlLng9ZWxlbWVudF90ZXh0KHNpemU9OSksIGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoc2l6ZT05KSwgDQogICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KHNpemU9OSksIGF4aXMudGV4dC55PWVsZW1lbnRfdGV4dChzaXplPTkpKSsgIyMgY2hhbmdlIHRoZSB0ZXh0IHNpemUgYXMgbmVjY2Vzc2FyeQ0KICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLCBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpDQpmaWdfaW4gPC0gcDEgKyBhbm5vdGF0aW9uX2N1c3RvbShnZ3Bsb3RHcm9iKHAxMDApLCB4bWluID0gNDAsIHhtYXggPSA1NiwgeW1pbiA9IDcsIHltYXggPSAxNikgKyAjIyBwbGFjZSB0aGUgaW5zZXJ0DQogICBhbm5vdGF0ZSgicmVjdCIsIHhtaW4gPSA3NCwgeG1heCA9IDc5LCB5bWluID0gNiwgeW1heCA9IDEwLjUsDQogIGFscGhhID0gLjIpICMjIHVzZSB0aGlzIHRvIGhpZ2hsaWdodCB0aGUgYXJlYSBvZiB0aGUgaW5zZXJ0IHBsb3QNCmBgYA0KDQpgYGB7ciBmaWcuaGVpZ2h0ID0gMTAsIGZpZy53aWR0aCA9IDE4fQ0KZ2dzYXZlKCBmaWxlbmFtZSA9IGZpbGUucGF0aCgiU2NyaXB0IiwgIk91dHB1dCIsIlBsb3RzIiwiaW5zZXJ0X3Bsb3Quc3ZnIiksIHBsb3QgPSBmaWdfaW4sIHdpZHRoID0gMTAsIGhlaWdodCA9IDYsIGRwaSA9IDMwMCkNCg0KcHJpbnQoZmlnX2luKQ0KYGBgDQojIyBDcmVhdGluZyBhIEhEUiBwbG90IHRvIHNpbXBsaWZ5IHlvdXIgZGF0YS4NClNpbXBsaWZ5aW5nIHRoZSBkYXRhIHdlIGNyZWF0ZSB0byBtYWtlIG1vcmUgdmlzdWFsbHkgY29tcGVsbGluZyBmaWd1cmVzIGNhbiBiZSBhY2hlaXZlZCB1c2luZyBoaWdoZXN0IGRlbnNpdHkgcmVnaW9ucy4gVGhlIGZvbGxvd2luZyBjb2RlIHBlcm1pdHMgdGhpcyBhcyBhbiBhZGRpdGlvbiB0byB0aGUgcHJldmlvc3VseSBjcmVhdGVkIHBsb3RzLiBJdCBjYW4gYmUgYWRkZWQgZWFzaWx5IHRvIGFueSBvZiB0aGUgcHJldmlvdXNseSBjcmVhdGVkIHBsb3RzIGJ5IGNoYW5naW5nIHRoZSBwIGNvZGUuIFZpc2liaWxpdHkgb2YgdGhlIGRlbnNpdHkgcmVnaW9ucyBjYW4gYmUgYXBwbGllZCB0byBqdXN0IHJlZmVyZW5jZSBkYXRhIG9yIGVudGlyZSBkYXRhc2V0cy4gT3BhY2l0eSBpcyB2YXJpZWQgdXNpbmcgdGhlIGFscGhhIGNvbW1hbmQgYW5kIHRoZSBwcm9iYWJpbGl0eSByYW5nZSBjYW4gYmUgYWx0ZXJlZCBpbiB0aGUgJ3Byb2JzJyBhcmd1bWVudC4gWW91IG1heSBuZWVkIHRvIHZhcnkgdGhlIHggYW5kIHkgYXhlcyBpbiBvcmRlciB0byBmaXQgdGhlIGZ1bGwgcmFuZ2UgaW4gdG8gdGhlIHBsb3QuDQoNCmBgYHtyfQ0KcDI4ZGVuIDwtIHAyOCArDQpnZW9tX2hkcihzdGF0PSAiaGRyIiwgbWV0aG9kID0gImtkZSIsIG5hLnJtID0gVFJVRSwgaW5oZXJpdC5hZXMgPSBUUlVFLCBhbHBoYSAgPSAwLjMsIHhsaW0gPSBjKDAsMTAwKSwgeWxpbSA9IGMoMCwzMCksIHNtb290aCA9IFRSVUUsIG4gPSAxMDAwLCBwcm9icyA9IGMoMC43NSkpDQpwcmludChwMjhkZW4pDQoNCg0KYGBgDQoNClRoZSBwbG90cyBhcmUgbmljZSBidXQgbWVzc3kgYW5kIHN0aWxsIGhhdmUgbG90cyBvZiBvdmVycGxvdHRpbmcuIElmIHlvdSBoYXZlIHBhcnRpY3VsYXJseSBtZXNzeSBkYXRhIEknZCBzdWdnZXN0IGNyZWF0aW5nIHBsb3QgJ2ZhY2V0cycgdXNpbmcgdGhlIGZvbGxvd2luZyBjb2RlLg0KDQpgYGB7cn0NCnAyOGRlbl9mYWNldCA8LSBwMjggKw0KZ2VvbV9oZHIobWV0aG9kID0gImtkZSIsIGFscGhhICA9IDAuNSwgeGxpbSA9IGMoMCwxMDApLCB5bGltID0gYygwLDMwKSwgc2hvdy5sZWdlbmQgPSBGQUxTRSwgc21vb3RoID0gVFJVRSwgbiA9IDEwMDAsIHByb2JzID0gYygwLjk1KSkgKw0KICBmYWNldF93cmFwKH4gaWQpDQoNCg0KcHJpbnQocDI4ZGVuX2ZhY2V0KQ0KYGBgDQoNCg0KYGBge3J9DQpjaGVtMiA8LSBkcGx5cjo6c2VsZWN0KGNoZW0sIC1Ub3RhbCkNCmNoZW0yIDwtIHJlbmFtZShjaGVtMiwgaWQyPWlkKQ0KZjE5IDwtIGdncGxvdChjaGVtLCBhZXMoeCA9IEFsMk8zLCB5ID0gQ2FPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCg0KZjE5IDwtIGYxOSArIA0KICAgIGdlb21fcG9pbnQoZGF0YSA9IGNoZW0yLCBpbmhlcml0LmFlcyA9IEZBTFNFLCBhZXMoeD1BbDJPMywgeSA9IENhTywgc2hhcGUgPSBpZDIpLCBjb2xvdXIgPSAiZ3JleTcwIikgKw0KICBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiQWwyTzMgKHd0JSkiKSt5bGFiKCJDYU8gKHd0JSkiKStzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gY2hlbXBhbGV0dGUpICsNCiAgVGVwaHJhLnRoZW1lICsNCiAgZmFjZXRfd3JhcCh+IGlkKQ0KDQpnZ3NhdmUoIGZpbGVuYW1lID0gZmlsZS5wYXRoKCJTY3JpcHQiLCAiT3V0cHV0IiwiUGxvdHMiLCJmYWNldGVkIHBsb3QucGRmIiksIHBsb3QgPSBmMTksIHdpZHRoID0gMjUsIGhlaWdodCA9IDE2LCB1bml0cyA9ICJjbSIsIGRwaSA9IDMwMCkNCg0KcHJpbnQoZjE5KQ0KDQpgYGANCmBgYHtyfQ0KdW5rbm93bnMgPC0gaGVyZTo6aGVyZSgiRGF0YSIsIkFyZHRvZV8xNi41X0JfdHlwZS5jc3YiKSAlPiUgcmVhZC5jc3YoKQ0KZ3QodW5rbm93bnMpDQpgYGANCmBgYHtyfQ0KdW5rbm93bl9zdW0gPC0gdW5rbm93bnMgJT4lIGdyb3VwX2J5KGlkMikgJT4lIGRwbHlyOjpzdW1tYXJpc2UoICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3VudD1uKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2lPMi49IG1lYW4oU2lPMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzEgPSBzZChTaU8yKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUaU8yLiA9IG1lYW4oVGlPMiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzIgPSBzZChUaU8yKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBbDJPMy4gPSBtZWFuKEFsMk8zKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfMyA9IHNkKEFsMk8zKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGZU90ID0gbWVhbihGZU8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldl80ID0gc2QoRmVPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBNbk8uPSBtZWFuKE1uTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzUgPSBzZChNbk8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1nTy49IG1lYW4oTWdPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZfNiA9IHNkKE1nTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2FPLj0gbWVhbihDYU8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldl83ID0gc2QoQ2FPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOYTJPLiA9IG1lYW4oTmEyTyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzggPSBzZChOYTJPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBLMk8uID0gbWVhbihLMk8pLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldl85ID0gc2QoSzJPKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQMk81LiA9IG1lYW4oUDJPNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2XzEwID0gc2QoUDJPNSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVG90YWwuPW1lYW4oVG90YWwpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldl8xMSA9IHNkKFRvdGFsKSkNCnVua25vd25fc3VtIDwtIHVua25vd25fc3VtICU+JSBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLm51bWVyaWMpLCB+IHJvdW5kKC4sIGRpZ2l0cyA9IDIpKSkNCnVua25vd25fc3VtICU+JSByZW5hbWUobGF5ZXIgPSBpZDIsIG4gPSBjb3VudCAsIFNpTzIgPSBTaU8yLiwgc2QxID0gZGV2XzEsIFRpTzIgPSBUaU8yLiAsIHNkMiA9IGRldl8yKQ0KDQpndCh1bmtub3duX3N1bSkNCmBgYA0KYGBge3J9DQpjaGVtX3JlZCA8LSBmaWx0ZXIoY2hlbSwgYWdlID09ICJXSSJ8YWdlID09ICJHUzIiKQ0KDQpjMjggPC0gZ2dwbG90KGNoZW1fcmVkLCBhZXMoeCA9IEZlTywgeSA9IENhTywgIGZpbGwgPSBpZCwgc2hhcGUgPSBpZCkpDQpjMjggPC0gYzI4ICsgDQogIGdlb21faGRyKG1ldGhvZCA9ICJrZGUiLCBhbHBoYSAgPSAwLjUsIHhsaW0gPSBjKDAsMTAwKSwgeWxpbSA9IGMoMCwzMCksIHNob3cubGVnZW5kID0gRkFMU0UsIHNtb290aCA9IFRSVUUsIG4gPSAxMDAwLCBwcm9icyA9IGMoMC45NSkpICsNCiAgIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogICAgZ2VvbV9wb2ludChkYXRhID0gdW5rbm93bnMsIGluaGVyaXQuYWVzID0gRkFMU0UsIGFlcyh4PUZlTywgeSA9IENhTywgc2hhcGUgPSBpZDIsIGZpbGwgPSBpZDIpLCBzaXplPTQsIGFscGhhPTAuOCkgKw0KICB4bGFiKCJGZU8gKHd0JSkiKSArDQogIHlsYWIoIkNhTyAod3QlKSIpICsgDQogICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjaGVtcGFsZXR0ZSkgKw0KICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPWMoMTo1LDcsMTEsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUpKSArDQogIFRlcGhyYS50aGVtZQ0KcHJpbnQoYzI4KQ0KYGBgDQpgYGB7cn0NCnUyOCA8LSBnZ3Bsb3QoY2hlbV9yZWQsIGFlcyh4ID0gRmVPLCB5ID0gQ2FPLCAgZmlsbCA9IGlkLCBzaGFwZSA9IGlkKSkNCnUyOCA8LSB1MjggKyBnZW9tX3BvaW50KGFlcyhmaWxsID0gaWQpLCBzaXplPTQsIGFscGhhPTAuOCkreGxhYigiRmVPICh3dCUpIikreWxhYigiQ2FPICh3dCUpIikrc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz1jKDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1LCAyMToyNSwgMjE6MjUsIDIxOjI1KSkrDQogICAgICBnZW9tX3BvaW50KGRhdGEgPSB1bmtub3ducywgaW5oZXJpdC5hZXMgPSBGQUxTRSwgYWVzKHg9RmVPLCB5ID0gQ2FPLCBzaGFwZSA9IGlkMiwgZmlsbCA9IGlkMiksIHNpemU9NCwgYWxwaGE9MC44KSArDQogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGNoZW1wYWxldHRlKSArDQogIFRlcGhyYS50aGVtZQ0KDQpnZ3Bsb3RseSh1MjgsIHdpZHRoID0gMTAwMCwgaGVpZ2h0ID0gODAwKQ0KYGBgDQoNCg0KDQojIFJlZmVyZW5jZXMNClIuIFcuIExlIE1haXRyZSAoZWRpdG9yKSwgQS4gU3RyZWNrZWlzZW4sIEIuIFphbmV0dGluLCBNLiBKLiBMZSBCYXMsIEIuIEJvbmluLCBQLiBCYXRlbWFuLCBHLiBCZWxsaWVuaSwgQS4gRHVkZWssIFMuIEVmcmVtb3ZhLCBKLiBLZWxsZXIsIEouIExhbWVyZSwgUC4gQS4gU2FiaW5lLCBSLiBTY2htaWQsIEguIFNvcmVuc2VuLCBhbmQgQS4gUi4gV29vbGxleSwgSWduZW91cyBSb2NrczogQSBDbGFzc2lmaWNhdGlvbiBhbmQgR2xvc3Nhcnkgb2YgVGVybXMsIFJlY29tbWVuZGF0aW9ucyBvZiB0aGUgSW50ZXJuYXRpb25hbCBVbmlvbiBvZiBHZW9sb2dpY2FsIFNjaWVuY2VzLCBTdWJjb21taXNzaW9uIG9mIHRoZSBTeXN0ZW1hdGljcyBvZiBJZ25lb3VzIFJvY2tzLiBDYW1icmlkZ2UgVW5pdmVyc2l0eSBQcmVzcywgMjAwMi4NCg0K